/**
* @file image_processor.cpp
*
* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "image_processor.h"

#include <set>
#include <atomic>
#include <memory>
#include <cstddef>
#include "securec.h"
#include "runtime/rt.h"
#include "utils/math_utils.h"
#include "common/log_inner.h"
#include "error_codes_inner.h"
#include "aicpu/dvpp/dvpp_def.h"
#include "aicpu/common/aicpu_task_struct.h"
#include "single_op/dvpp/common/dvpp_util.h"
#include "single_op/dvpp/mgr/dvpp_manager.h"

#define GET_PNG_VALUE(a, b, c, d)                                                                       \
    (static_cast<uint32_t>(((static_cast<uint32_t>(a)) << 24) | ((static_cast<uint32_t>(b)) << 16) |    \
        ((static_cast<uint32_t>(c)) << 8) | (static_cast<uint32_t>(d))))

namespace {
    constexpr uint32_t DVPP_PNGD_MAX_OUTPUT_SIZE = 4096U * 4096U * 4U * 2U;
}

namespace acl {
    namespace dvpp {
        namespace {
            constexpr int32_t EXIF_MARKER = (JPEG_APP0 + 1);
            constexpr uint16_t TIFF_LITTLE_ENDIAN = 0x4949U;
            constexpr uint16_t TIFF_BIG_ENDIAN = 0x4D4DU;
            constexpr uint16_t TIFF_ORIENTATION_TAG = 0x0112U;
            constexpr uint8_t JPEG_MARKER = 0xFFU;
            constexpr uint8_t MARK_SOI = 0xD8U;
            constexpr uint8_t MARK_EOI = 0xD9U;
            constexpr uint8_t MARK_SOS = 0xDAU;
            constexpr uint8_t NOT_JPEG_MARK = 0x00U;
            constexpr uint8_t JPEG_MARK_LENGTH_INFO_LENGTH = 2U; // length of JPEG MARK field length info
            constexpr uint8_t BYTE_LENGTH_IN_BIT = 8U;
            constexpr uint8_t MAX_JPEG_COMPONENT_NUM = 4U; // max component num of jpeg
            constexpr uint8_t JPEG_EACH_HUFFMAN_IDX_SPACE = 2U;
            constexpr uint8_t JPEG_SOS_EXT_LENGTH = 6U;
            constexpr uint8_t DC_HUFFMAN_NUM_SHIFT = 4U;
            constexpr uint8_t MAX_SUPPORT_HUFFMAN = 4U;
            constexpr char_t EXIF_HEADER[6] = {'E', 'x', 'i', 'f', 0, 0};
            constexpr char_t TIFF_HEADER_LE[4] = {0x49, 0x49, 0x2A, 0x00};
            constexpr char_t TIFF_HEADER_BE[4] = {0x4D, 0x4D, 0x00, 0x2A};
            enum OrientationValue {
                ORIENTATION_1 = 1,
                ORIENTATION_2,
                ORIENTATION_3,
                ORIENTATION_4,
                ORIENTATION_5,
                ORIENTATION_6,
                ORIENTATION_7,
                ORIENTATION_8
            };
            bool GetImageFormat(const jpeg_decompress_struct &libjpegHandler, acldvppJpegFormat *const format)
            {
                bool isValidFormat = false;
                // just support colorspace JCS_GRAYSCALE or JCS_YCbCr
                if ((libjpegHandler.jpeg_color_space == JCS_YCbCr) ||
                    (libjpegHandler.jpeg_color_space == JCS_GRAYSCALE)) {
                    constexpr size_t y = 0U;
                    constexpr size_t u = 1U;
                    constexpr size_t v = 2U;
                    // yuv400: component 1 1x1
                    // yuv420: component 3 2x2 1x1 1x1
                    // yuv422: component 3 2x1 1x1 1x1
                    // yuv440: component 3 1x2 1x1 1x1
                    // yuv444: component 3 1x1 1x1 1x1
                    if ((libjpegHandler.num_components == 1) &&
                        (libjpegHandler.comp_info[y].h_samp_factor == libjpegHandler.comp_info[y].v_samp_factor)) {
                            isValidFormat = true;
                            *format = ACL_JPEG_CSS_GRAY;
                            return isValidFormat;
                    }
                    if ((libjpegHandler.num_components == 3) &&
                        (libjpegHandler.comp_info[u].h_samp_factor == libjpegHandler.comp_info[v].h_samp_factor) &&
                        (libjpegHandler.comp_info[u].v_samp_factor == libjpegHandler.comp_info[v].v_samp_factor)) {
                        if (libjpegHandler.comp_info[y].h_samp_factor ==
                            ((libjpegHandler.comp_info[u].h_samp_factor) * 2)) {
                            if (libjpegHandler.comp_info[y].v_samp_factor ==
                                ((libjpegHandler.comp_info[u].v_samp_factor) * 2)) {
                                isValidFormat = true;
                                *format = ACL_JPEG_CSS_420;
                                return isValidFormat;
                            }
                            if (libjpegHandler.comp_info[y].v_samp_factor ==
                                       libjpegHandler.comp_info[u].v_samp_factor) {
                                isValidFormat = true;
                                *format = ACL_JPEG_CSS_422;
                                return isValidFormat;
                            }
                        }
                        if (libjpegHandler.comp_info[y].h_samp_factor ==
                                   libjpegHandler.comp_info[u].h_samp_factor) {
                            if (libjpegHandler.comp_info[y].v_samp_factor ==
                                libjpegHandler.comp_info[u].v_samp_factor) {
                                isValidFormat = true;
                                *format = ACL_JPEG_CSS_444;
                                return isValidFormat;
                            }
                            if (libjpegHandler.comp_info[y].v_samp_factor ==
                                       (libjpegHandler.comp_info[u].v_samp_factor * 2)) {
                                isValidFormat = true;
                                *format = ACL_JPEG_CSS_440;
                                return isValidFormat;
                            }
                        }
                    }
                }
                return isValidFormat;
            }
            uint16_t GetU16(const uint8_t *const data, const uint16_t endian)
            {
                if (endian == TIFF_BIG_ENDIAN) {
                    return (static_cast<uint16_t>(static_cast<uint16_t>(data[0]) << 8U)) |
                        static_cast<uint16_t>(data[1]);
                } else {
                    return (static_cast<uint16_t>(static_cast<uint16_t>(data[1]) << 8U)) |
                        static_cast<uint16_t>(data[0]);
                }
            }
            uint32_t GetU32(const uint8_t *const data, const uint16_t endian)
            {
                if (endian == TIFF_BIG_ENDIAN) {
                    return (static_cast<uint32_t>(data[0]) << 24U) | (static_cast<uint32_t>(data[1]) << 16U) |
                           (static_cast<uint32_t>(data[2]) << 8U) | static_cast<uint32_t>(data[3]);
                } else {
                    return (static_cast<uint32_t>(data[3]) << 24U) | (static_cast<uint32_t>(data[2]) << 16U) |
                           (static_cast<uint32_t>(data[1]) << 8U) | static_cast<uint32_t>(data[0]);
                }
            }
            jpeg_saved_marker_ptr JpegdFindExifMarker(const j_decompress_ptr cinfo)
            {
                jpeg_saved_marker_ptr tmpMarker = cinfo->marker_list;
                while (tmpMarker != nullptr) {
                    // 6 means ignore EXIF heder
                    if ((static_cast<int32_t>(tmpMarker->marker) == EXIF_MARKER) && (tmpMarker->data_length >= 6U) &&
                       (memcmp(tmpMarker->data, EXIF_HEADER, 6U) == 0)) {
                        return tmpMarker;
                    }
                    tmpMarker = tmpMarker->next;
                }
                return nullptr;
            }
            bool JudgeNeedOrientation(const j_decompress_ptr cinfo)
            {
                const jpeg_saved_marker_ptr jpegExifMarker = JpegdFindExifMarker(cinfo);
                if (jpegExifMarker == nullptr) {
                    return false;
                }
                uint16_t orientation = 0U;
                uint64_t pos = 6U; // 6 means ignore EXIF heder
                uint16_t endian = 0U;

                // 8 means TIFF header
                if ((pos + 8U) > jpegExifMarker->data_length) {
                    return false;
                }
                if (memcmp(&jpegExifMarker->data[pos], TIFF_HEADER_LE, 4U) == 0) {
                    endian = TIFF_LITTLE_ENDIAN;
                } else if (memcmp(&jpegExifMarker->data[pos], TIFF_HEADER_BE, 4U) == 0) {
                    endian = TIFF_BIG_ENDIAN;
                } else {
                    return false;
                }

                pos += GetU32(&jpegExifMarker->data[pos] + 4, endian);
                if ((pos + 2U) > jpegExifMarker->data_length) {
                    return false;
                }
                uint64_t entries = GetU16(&jpegExifMarker->data[pos], endian);
                pos += 2U;

                if ((pos + (entries * 12U)) > jpegExifMarker->data_length) {
                    return false;
                }

                while ((entries) != 0U) {
                    --entries;
                    const uint16_t tag = GetU16(&jpegExifMarker->data[pos], endian);
                    if (tag == TIFF_ORIENTATION_TAG) {
                        const uint16_t format = GetU16(&jpegExifMarker->data[pos + 2U], endian);
                        const uint16_t num = static_cast<uint16_t>(GetU32(&jpegExifMarker->data[pos + 4U], endian));
                        if ((format != 3U) || (num != 1U)) { // orientation protocal
                            return false;
                        }
                        orientation = GetU16(&jpegExifMarker->data[pos + 8U], endian);
                        break;
                    }
                    pos += 12U;
                }
                ACL_LOG_INFO("orientation is %u", static_cast<int32_t>(orientation));
                if ((orientation >= static_cast<uint16_t>(ORIENTATION_5)) &&
                    (orientation <= static_cast<uint16_t>(ORIENTATION_8))) {
                    ACL_LOG_INFO("This image need orientation");
                    return true;
                }
                return false;
            }
        }

    void ImageProcessor::SetDvppWaitTaskType(acldvppChannelDesc *const channelDesc) const
    {
        channelDesc->dvppWaitTaskType = NOTIFY_TASK;
        ACL_LOG_INFO("dvpp wait task type is notify");
    }

    void ImageProcessor::ResetEvent(const acldvppChannelDesc *const channelDesc, const rtStream_t rtStream) const
    {
        if (channelDesc->dvppWaitTaskType == EVENT_TASK) {
            (void)rtEventReset(static_cast<rtEvent_t>(channelDesc->notify), rtStream);
        }
    }

    aclError ImageProcessor::DvppCreateChannelWithNotify(acldvppChannelDesc *const channelDesc) const
    {
        SetDvppWaitTaskType(channelDesc);

        // create notify for dvpp channel desc
        const aclError aclRet = CreateNotifyForDvppChannel(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Create][Notify]create notify for dvpp channel failed, errorCode = %d", aclRet);
            return aclRet;
        }

        rtStream_t rtStream = nullptr;
        const rtError_t rtCreate = rtStreamCreate(&rtStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtCreate != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Stream]create stream failed, errorCode = %d", rtCreate);
            if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
                (void)rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
            } else {
                (void)rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
            }
            channelDesc->notify = nullptr;
            return ACL_GET_ERRCODE_RTS(rtCreate);
        }

        // clear event task, prevent resource residue
        ResetEvent(channelDesc, rtStream);

        const size_t size = CalDevDvppStructRealUsedSize(&channelDesc->dvppDesc);
        if (aclRunMode_ == ACL_HOST) {
            // if online memcpy data to device (both async and sync copy type are OK for this api)
            const rtError_t rtRet = rtMemcpyAsync(channelDesc->dataBuffer.data, channelDesc->dataBuffer.length,
                                                  static_cast<const void *>(&channelDesc->dvppDesc), size,
                                                  RT_MEMCPY_HOST_TO_DEVICE, rtStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to device memory failed, size = %zu, "
                    "runtime errorCode = %d", size, rtRet);
                DestroyNotifyAndStream(channelDesc, rtStream);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        // create channel have 1 output and 1 input
        constexpr uint32_t ioAddrNum = 2U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        char_t args[argsSize] = {};
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args);
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->cmdListBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        rtError_t rtRet = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
            acl::dvpp::DVPP_KERNELNAME_CREATE_CHANNEL,
            1U, // blockDim default 1
            args,
            argsSize,
            nullptr, // no need smDesc
            rtStream);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Channel]dvpp create channel call rtCpuKernelLaunch failed, "
                "runtime errorCode = %d.", rtRet);
            DestroyNotifyAndStream(channelDesc, rtStream);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        if (aclRunMode_ == ACL_HOST) {
            rtRet = rtMemcpyAsync(&channelDesc->dvppDesc, size,
                static_cast<const void *>(channelDesc->dataBuffer.data), size,
                RT_MEMCPY_DEVICE_TO_HOST, rtStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to host memory failed, size = %zu, "
                    "runtime errorCode = %d", size, rtRet);
                DestroyNotifyAndStream(channelDesc, rtStream);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        const rtError_t rtSynchronize = rtStreamSynchronize(rtStream);
        if (rtSynchronize != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Copy][Stream]synchronize stream failed, errorCode = %d", rtSynchronize);
            DestroyNotifyAndStream(channelDesc, rtStream);
            return ACL_GET_ERRCODE_RTS(rtSynchronize);
        }

        // retCode = 0 : success
        if (channelDesc->dvppDesc.retCode != 0U) {
            ACL_LOG_INNER_ERROR("[Create][Channel]create channel failed, errorCode = %d",
                channelDesc->dvppDesc.retCode);
            DestroyNotifyAndStream(channelDesc, rtStream);
            return ACL_ERROR_INTERNAL_ERROR;
        }

        const rtError_t rtDestroy = rtStreamDestroy(rtStream);
        if (rtDestroy != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Stream]destroy stream failed, runtime errorCode = %d", rtDestroy);
            if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
                (void)rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
            } else {
                (void)rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
            }
            channelDesc->notify = nullptr;
            return ACL_GET_ERRCODE_RTS(rtDestroy);
        }

        channelDesc->isChannelAvailable = true;
        ACL_LOG_INFO("create dvpp channel with notify success, notifyId = %u", channelDesc->dvppDesc.notifyId);
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppCreateChannelWithoutNotify(acldvppChannelDesc *const channelDesc) const
    {
        rtStream_t rtStream = nullptr;
        const rtError_t rtCreate = rtStreamCreate(&rtStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtCreate != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Stream]create stream failed, errorCode = %d", rtCreate);
            return ACL_GET_ERRCODE_RTS(rtCreate);
        }

        const size_t size = CalDevDvppStructRealUsedSize(&channelDesc->dvppDesc);
        if (aclRunMode_ == ACL_HOST) {
            // if online memcpy data to device (both async and sync copy type are OK for this api)
            const rtError_t rtRet = rtMemcpyAsync(channelDesc->dataBuffer.data, channelDesc->dataBuffer.length,
                                                  static_cast<const void *>(&channelDesc->dvppDesc), size,
                                                  RT_MEMCPY_HOST_TO_DEVICE, rtStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to device memory failed, size = %zu, "
                    "runtime errorCode = %d", size, rtRet);
                DestroyStream(rtStream);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        // create channel have 1 output and 1 input
        constexpr uint32_t ioAddrNum = 2U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        char_t args[argsSize] = {};
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args);
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->cmdListBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        rtError_t rtRet = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
            acl::dvpp::DVPP_KERNELNAME_CREATE_CHANNEL_V2,
            1U, // blockDim default 1
            args,
            argsSize,
            nullptr, // no need smDesc
            rtStream);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Channel]dvpp create channel call rtCpuKernelLaunch failed, "
                "runtime errorCode = %d.", rtRet);
            DestroyStream(rtStream);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }

        if (aclRunMode_ == ACL_HOST) {
            rtRet = rtMemcpyAsync(&channelDesc->dvppDesc, size,
                static_cast<const void *>(channelDesc->dataBuffer.data), size,
                RT_MEMCPY_DEVICE_TO_HOST, rtStream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Copy][Mem]memcpy to host memory failed, size = %zu, "
                    "runtime errorCode = %d", size, rtRet);
                DestroyStream(rtStream);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        const rtError_t rtSynchronize = rtStreamSynchronize(rtStream);
        if (rtSynchronize != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]synchronize stream failed, runtime errorCode = %d", rtSynchronize);
            DestroyStream(rtStream);
            return ACL_GET_ERRCODE_RTS(rtSynchronize);
        }

        // retCode = 0 : success
        if (channelDesc->dvppDesc.retCode != 0U) {
            ACL_LOG_INNER_ERROR("[Create][Channel]create channel failed, errorCode = %d",
                channelDesc->dvppDesc.retCode);
            DestroyStream(rtStream);
            return ACL_ERROR_INTERNAL_ERROR;
        }

        const rtError_t rtDestroy = rtStreamDestroy(rtStream);
        if (rtDestroy != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Stream]destroy stream failed, runtime errorCode = %d", rtDestroy);
            return ACL_GET_ERRCODE_RTS(rtDestroy);
        }

        channelDesc->isChannelAvailable = true;
        ACL_LOG_INFO("create dvpp channel without notify success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppMallocCmdlistBuffer(acldvppChannelDesc *const channelDesc) const
    {
        ACL_LOG_INFO("start to execute DvppMallocCmdlistBuffer");
        if (!DvppNeedCmdlist(channelDesc)) {
            ACL_LOG_INFO("no need set cmdlist buffer");
            return ACL_SUCCESS;
        }
        if (channelDesc->cmdListBuffer.data != nullptr) {
            ACL_LOG_INFO("cmdlist buffer is not nullptr");
            return ACL_SUCCESS;
        }
        // alloc device mem for cmdListBuffer
        void *tmpData = nullptr;
        const size_t tmpDataSize = GetCmdlistBuffSize();
        const uint32_t flag = DvppNeedCmdlistSetReadOnly() ? static_cast<uint32_t>(RT_MEMORY_ATTRIBUTE_READONLY) :
            static_cast<uint32_t>(RT_MEMORY_ATTRIBUTE_DEFAULT);
        const aclError ret = DvppMallocInternal(&tmpData, tmpDataSize, flag);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Dvpp][Malloc]malloc cmdlistReadOnly memory for channel failed, "
                "size = %zu", tmpDataSize);
            return ACL_GET_ERRCODE_RTS(ret);
        }
        channelDesc->cmdListBuffer.data = tmpData;
        channelDesc->cmdListBuffer.length = tmpDataSize;
        return ACL_SUCCESS;
    }

    bool ImageProcessor::DvppNeedCmdlistWrite() const
    {
        return false;
    }

    bool ImageProcessor::DvppNeedCmdlist(acldvppChannelDesc *const channelDesc) const
    {
        (void)channelDesc;
        return true;
    }

    bool ImageProcessor::DvppNeedCmdlistSetReadOnly() const
    {
        return true;
    }

    aclError ImageProcessor::DvppMallocCmdlistBufferWrite(acldvppChannelDesc *const channelDesc) const
    {
        ACL_LOG_INFO("start to execute DvppMallocCmdlistBufferWrite");
        if (channelDesc->cmdListBufferWrite.data != nullptr) {
            ACL_LOG_INFO("cmdlist write buffer is not nullptr");
            return ACL_SUCCESS;
        }
        // alloc device mem for cmdListBuffer write
        void *tmpData = nullptr;
        const size_t tmpDataSize = GetCmdlistBuffSize();
        const aclError ret = DvppMallocInternal(&tmpData, tmpDataSize,
            static_cast<uint32_t>(RT_MEMORY_ATTRIBUTE_DEFAULT));
        if (ret != ACL_SUCCESS) {
            ACL_LOG_CALL_ERROR("[Dvpp][Malloc]malloc cmdlistReadOnly memory for channel failed, "
                "size = %zu", tmpDataSize);
            return ACL_GET_ERRCODE_RTS(ret);
        }
        channelDesc->cmdListBufferWrite.data = tmpData;
        channelDesc->cmdListBufferWrite.length = tmpDataSize;
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppCreateChannel(acldvppChannelDesc *const channelDesc)
    {
        return DvppImageCreateChannel(channelDesc);
    }

    aclError ImageProcessor::DvppImageCreateChannel(acldvppChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("start to execute acldvppCreateChannel");
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_OK(DvppMallocCmdlistBuffer(channelDesc));
        const aclError aclRet = SetDvppParamToDvppChannel(channelDesc);
        if (aclRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Set][DvppParam]set dvpp parameter failed, errorCode = %d", aclRet);
            return ACL_ERROR_INVALID_PARAM;
        }

        if (channelDesc->isNeedNotify) {
            return DvppCreateChannelWithNotify(channelDesc);
        } else {
            return DvppCreateChannelWithoutNotify(channelDesc);
        }
    }

    aclError ImageProcessor::DvppDestroyChannelWithNotify(acldvppChannelDesc *const channelDesc) const
    {
        // destroy channel have 1 input
        constexpr uint32_t ioAddrNum = 1U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        char_t args[argsSize] = {};
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args);
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        rtStream_t rtStream = nullptr;
        const rtError_t rtCreate = rtStreamCreate(&rtStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtCreate != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Stream]create stream failed, runtime errorCode = %d", rtCreate);
            if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
                (void)rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
            } else {
                (void)rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
            }
            channelDesc->notify = nullptr;
            return ACL_GET_ERRCODE_RTS(rtCreate);
        }
        rtError_t rtRetVal = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
            acl::dvpp::DVPP_KERNELNAME_DESTROY_CHANNEL,
            1U, // blockDim default 1
            args,
            argsSize,
            nullptr, // no need smDesc
            rtStream);
        if (rtRetVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Channel]dvpp destroy channel call rtCpuKernelLaunch failed, "
                "runtime errorCode = %d.", rtRetVal);
            DestroyNotifyAndStream(channelDesc, rtStream);
            return ACL_GET_ERRCODE_RTS(rtRetVal);
        }

        const rtError_t rtSynchronizeVal = rtStreamSynchronize(rtStream);
        if (rtSynchronizeVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]synchronize stream failed, runtime errorCode = %d.", rtSynchronizeVal);
            DestroyNotifyAndStream(channelDesc, rtStream);
            return ACL_GET_ERRCODE_RTS(rtSynchronizeVal);
        }

        const rtError_t rtDestroyVal = rtStreamDestroy(rtStream);
        if (rtDestroyVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Stream]destroy stream failed, runtime errorCode = %d.", rtDestroyVal);
            if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
                (void)rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
            } else {
                (void)rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
            }
            channelDesc->notify = nullptr;
            return ACL_GET_ERRCODE_RTS(rtDestroyVal);
        }

        if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
            rtRetVal = rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
        } else {
            rtRetVal = rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
        }
        if (rtRetVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Notify]fail to destroy Notify, runtime errorCode = %d.", rtRetVal);
            return ACL_GET_ERRCODE_RTS(rtRetVal);
        }
        channelDesc->notify = nullptr;
        channelDesc->isChannelAvailable = false;
        ACL_LOG_INFO("destroy dvpp channel with notify success, notifyId = %u.", channelDesc->dvppDesc.notifyId);
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppDestroyChannelWithoutNotify(acldvppChannelDesc *const channelDesc) const
    {
        // destroy channel have 1 input
        constexpr uint32_t ioAddrNum = 1U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        char_t args[argsSize] = {};
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args);
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);

        rtStream_t rtStream = nullptr;
        const rtError_t rtCreate = rtStreamCreate(&rtStream, static_cast<int32_t>(RT_STREAM_PRIORITY_DEFAULT));
        if (rtCreate != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Create][Stream]create stream failed, errorCode = %d", rtCreate);
            return ACL_GET_ERRCODE_RTS(rtCreate);
        }
        const rtError_t rtRetVal = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
            acl::dvpp::DVPP_KERNELNAME_DESTROY_CHANNEL_V2,
            1U, // blockDim default 1
            args,
            argsSize,
            nullptr, // no need smDesc
            rtStream);
        if (rtRetVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Channel]dvpp destroy channel call "
                "rtCpuKernelLaunch failed, ret=%d.", rtRetVal);
            DestroyStream(rtStream);
            return ACL_GET_ERRCODE_RTS(rtRetVal);
        }

        const rtError_t rtSynchronizeVal = rtStreamSynchronize(rtStream);
        if (rtSynchronizeVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Sync][Stream]synchronize stream failed, errorCode = %d", rtSynchronizeVal);
            DestroyStream(rtStream);
            return ACL_GET_ERRCODE_RTS(rtSynchronizeVal);
        }

        const rtError_t rtDestroyVal = rtStreamDestroy(rtStream);
        if (rtDestroyVal != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Destroy][Stream]destroy stream failed, errorCode = %d", rtDestroyVal);
            return ACL_GET_ERRCODE_RTS(rtDestroyVal);
        }

        channelDesc->isChannelAvailable = false;
        ACL_LOG_INFO("destroy dvpp channel without notify success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppDestroyChannel(acldvppChannelDesc *const channelDesc)
    {
        return DvppImageDestroyChannel(channelDesc);
    }

    aclError ImageProcessor::DvppImageDestroyChannel(acldvppChannelDesc *const channelDesc)
    {
        ACL_LOG_INFO("start to execute acldvppDestroyChannel");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);

        if (channelDesc->isNeedNotify) {
            return DvppDestroyChannelWithNotify(channelDesc);
        } else {
            return DvppDestroyChannelWithoutNotify(channelDesc);
        }
    }

    aclError ImageProcessor::LaunchDvppWaitTask(const acldvppChannelDesc *const channelDesc,
        const aclrtStream stream) const
    {
        rtError_t rtRetCodeVal;
        if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
            rtRetCodeVal = rtNotifyWait(static_cast<rtNotify_t>(channelDesc->notify), stream);
            if (rtRetCodeVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Wait][Notify]wait for a notify to stream failed, "
                    "runtime errorCode = %d", rtRetCodeVal);
                return ACL_GET_ERRCODE_RTS(rtRetCodeVal);
            }
        } else {
            rtRetCodeVal = rtStreamWaitEvent(stream, static_cast<rtEvent_t>(channelDesc->notify));
            if (rtRetCodeVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Wait][Event]wait for a event to stream failed, "
                    "runtime errorCode = %d", rtRetCodeVal);
                return ACL_GET_ERRCODE_RTS(rtRetCodeVal);
            }
            rtRetCodeVal = rtEventReset(static_cast<rtEvent_t>(channelDesc->notify), stream);
            if (rtRetCodeVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Reset][Event]reset a event to stream failed, "
                    "runtime errorCode = %d", rtRetCodeVal);
                return ACL_GET_ERRCODE_RTS(rtRetCodeVal);
            }
        }

        return ACL_SUCCESS;
    }

    aclError ImageProcessor::LaunchDvppTask(const acldvppChannelDesc *const channelDesc, const char_t *const args,
        const uint32_t argsSize, const char_t *const kernelName, const aclrtStream stream) const
    {
        if (channelDesc->isNeedNotify) {
            const rtError_t rtRetCodeVal = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
                                                             kernelName,
                                                             1U, // blockDim default 1
                                                             args,
                                                             argsSize,
                                                             nullptr, // no need smDesc
                                                             stream);
            if (rtRetCodeVal != RT_ERROR_NONE) {
                ACL_LOG_INNER_ERROR("[Call][KernelLaunch]dvpp call rtCpuKernelLaunch failed, "
                    "runtime errorCode = %d.", rtRetCodeVal);
                return ACL_GET_ERRCODE_RTS(rtRetCodeVal);
            }

            const aclError launchTaskRet = LaunchDvppWaitTask(channelDesc, stream);
            if (launchTaskRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Launch][WaitTask]launch dvpp wait task failed, errorCode = %d.", launchTaskRet);
                return launchTaskRet;
            }
            ACL_LOG_INFO("Launch dvpp tasks success, notifyId = %u", channelDesc->dvppDesc.notifyId);
        } else {
            std::string kernelNameV2 = kernelName;
            (void)kernelNameV2.append("V2");
            const rtError_t rtRetCodeVal = rtCpuKernelLaunch(acl::dvpp::DVPP_KERNELS_SONAME,
                                                             kernelNameV2.c_str(),
                                                             1U, // blockDim default 1
                                                             args,
                                                             argsSize,
                                                             nullptr, // no need smDesc
                                                             stream);
            if (rtRetCodeVal != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Call][Kernel]dvpp call rtCpuKernelLaunch failed, "
                    "runtime errorCode = %d.", rtRetCodeVal);
                return ACL_GET_ERRCODE_RTS(rtRetCodeVal);
            }
        }

        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcResizeAsync(acldvppChannelDesc *const channelDesc,
                                                   acldvppPicDesc *const inputDesc,
                                                   acldvppPicDesc *const outputDesc,
                                                   acldvppResizeConfig *const resizeConfig,
                                                   const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppVpcResizeAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        // check vpc input format
        const aclError validResizeInputRet = ValidateVpcInputFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validResizeInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Format]input picture describe format verify failed, "
                "result = %d, format = %u.", validResizeInputRet, inputDesc->dvppPicDesc.format);
            return validResizeInputRet;
        }

        // check vpc output format
        const aclError validResizeOutputRet = ValidateVpcOutputFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validResizeOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Format]output picture describe format verify failed, "
                "result = %d, format = %u.", validResizeOutputRet, outputDesc->dvppPicDesc.format);
            return validResizeOutputRet;
        }
        // check dvpp resize config
        const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
        if (validResizeConfigRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][ResizeConfig]resize config acldvppResizeConfig verify failed, "
                "result = %d.", validResizeConfigRet);
            return validResizeConfigRet;
        }

        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const size_t resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        constexpr size_t configOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        const auto memcpyRet = memcpy_s(args.get() + configOffset, (argsSize - configOffset),
            &(resizeConfig->dvppResizeConfig), resizeConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Mem]copy resize config to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize input picture desc failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }
            cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize output picture desc to device failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            acl::dvpp::DVPP_KERNELNAME_RESIZE, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][DvppTask]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy resize output pic desc from device failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("Launch vpc resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::ValidateParamForDvppVpcCropResizePaste(const acldvppChannelDesc *const channelDesc,
                                                                    const acldvppPicDesc *const inputDesc,
                                                                    const acldvppPicDesc *const outputDesc,
                                                                    const acldvppRoiConfig *const cropArea,
                                                                    const acldvppRoiConfig *const pasteArea,
                                                                    const bool pasteAreaSwitch,
                                                                    const acldvppResizeConfig *const resizeConfig,
                                                                    const bool resizeConfigSwitch,
                                                                    uint32_t &resizeConfigSize) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropArea);
        if (pasteAreaSwitch) {
            ACL_REQUIRES_NOT_NULL(pasteArea);
        }
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
            const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
            if (validResizeConfigRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][DvppResizeConfig]resize config acldvppResizeConfig "
                    "verify failed, errorCode = %d.", validResizeConfigRet);
                return validResizeConfigRet;
            }
            resizeConfigSize = static_cast<uint32_t>(CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig));
        }

        // check vpc input format
        const aclError validCropInputRet = ValidateVpcInputFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validCropInputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][VpcInputFormat]input acldvppPicDesc format verify failed, "
                "result = %d, format = %u.", validCropInputRet, inputDesc->dvppPicDesc.format);
            return validCropInputRet;
        }

        // check vpc output format
        const aclError validCropOutputRet = ValidateVpcOutputFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validCropOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][VpcOutputFormat]output acldvppPicDesc format verify failed,"
                "result = %d, format = %u.", validCropOutputRet, outputDesc->dvppPicDesc.format);
            return validCropOutputRet;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcCropResizeAsync(const acldvppChannelDesc *const channelDesc,
                                                    const acldvppPicDesc *const inputDesc,
                                                    const acldvppPicDesc *const outputDesc,
                                                    const acldvppRoiConfig *const cropArea,
                                                    acldvppResizeConfig *const resizeConfig,
                                                    const bool resizeConfigSwitch,
                                                    const aclrtStream stream) const
    {
        uint32_t resizeConfigSize = 0U;
        const aclError validateRet = ValidateParamForDvppVpcCropResizePaste(channelDesc, inputDesc, outputDesc,
            cropArea, nullptr, false, resizeConfig, resizeConfigSwitch, resizeConfigSize);
        if (validateRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Param]verify params for DvppVpcCropResize failed, ret = %d", validateRet);
            return validateRet;
        }
        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t roiConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + roiConfigSize +
            resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto cpuParamHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        cpuParamHead->length = static_cast<uint32_t>(argsSize);
        cpuParamHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        // copy roi config
        constexpr size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        auto cpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
            &(cropArea->dvppRoiConfig), roiConfigSize);
        if (cpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][CropArea]copy crop area to args failed, result = %d.", cpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError copyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", copyRet);
                return copyRet;
            }

            copyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc to device failed, errorCode = %d.", copyRet);
                return copyRet;
            }
        }
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_CROP;
        // copy resize config
        if (resizeConfigSwitch) {
            constexpr size_t resizeConfigOffset = cropAreaOffset + roiConfigSize;
            cpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                &(resizeConfig->dvppResizeConfig), static_cast<size_t>(resizeConfigSize));
            if (cpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Cpoy][ResizeConfig]copy resize config to args failed, result = %d.", cpyRet);
                return ACL_ERROR_FAILURE;
            }
            kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_RESIZE;
        }
        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError copyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (copyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.",
                    copyRet);
                return copyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                       acldvppPicDesc *const inputDesc,
                                                       acldvppPicDesc *const outputDesc,
                                                       acldvppRoiConfig *const cropArea,
                                                       acldvppResizeConfig *const resizeConfig,
                                                       const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizeAsync");
        const auto ret = DvppVpcCropResizeAsync(channelDesc, inputDesc, outputDesc, cropArea,
            resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][DvppVpcCropResizeAsync]execute acldvppVpcCropResizeAsync failed, "
                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop and resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropAsync(acldvppChannelDesc *const channelDesc,
                                                 acldvppPicDesc *const inputDesc,
                                                 acldvppPicDesc *const outputDesc,
                                                 acldvppRoiConfig *const cropArea,
                                                 const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAsync");
        const auto ret = DvppVpcCropResizeAsync(channelDesc, inputDesc, outputDesc, cropArea, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][DvppVpcCrop]execute acldvppVpcCropAsync failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcBatchCropResizeAsync(const acldvppChannelDesc *const channelDesc,
                                                         acldvppBatchPicDesc *const srcBatchPicDescs,
                                                         const uint32_t *const roiNums,
                                                         const uint32_t size,
                                                         acldvppBatchPicDesc *const dstBatchPicDescs,
                                                         acldvppRoiConfig *cropAreas[],
                                                         acldvppResizeConfig *const resizeConfig,
                                                         const bool resizeConfigSwitch,
                                                         const aclrtStream stream) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropAreas);
        ACL_REQUIRES_NOT_NULL(roiNums);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
        }

        // valid input param
        const std::unique_ptr<uint16_t[]> roiNumsPtr(new (std::nothrow)uint16_t[size]);
        if (roiNumsPtr == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][BatchCrop]create batch crop roiNums pointer failed, "
                "roiNums size = %u.", size);
            return ACL_ERROR_INVALID_PARAM;
        }
        uint32_t totalRoiNums = 0U;
        const aclError validParamRet = ValidateAndConvertVpcBatchParams(srcBatchPicDescs,
                                                                        dstBatchPicDescs,
                                                                        roiNums,
                                                                        size,
                                                                        roiNumsPtr.get(),
                                                                        totalRoiNums,
                                                                        BATCH_ROI_MAX_SIZE,
                                                                        resizeConfig);
        if (validParamRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][CropParam]verify batch crop param failed, errorCode = %d.", validParamRet);
            return validParamRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy input batch pic desc data
            aclError cpyAsyncRet = CopyDvppBatchPicDescAsync(srcBatchPicDescs,
                                                             ACL_MEMCPY_HOST_TO_DEVICE,
                                                             size,
                                                             stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy input batch pic desc to device failed, "
                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }

            // copy output batch pic desc data
            cpyAsyncRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                    ACL_MEMCPY_HOST_TO_DEVICE,
                                                    totalRoiNums,
                                                    stream);
            if (cpyAsyncRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]async copy output batch pic desc to device failed, "
                    "result = %d.", cpyAsyncRet);
                return cpyAsyncRet;
            }
        } else {
            // set data buffer for input batch pic desc
            aclError setDataRet = SetDataBufferForBatchPicDesc(srcBatchPicDescs, size);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for src batch pic desc "
                    "failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }

            setDataRet = SetDataBufferForBatchPicDesc(dstBatchPicDescs, totalRoiNums);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]dvpp batch crop set data buffer for dst batch pic desc "
                    "failed, errorCode = %d.", setDataRet);
                return setDataRet;
            }
        }

        void *const roiNumsAddress = static_cast<void *>(roiNumsPtr.get());
        const VpcBatchParams batchParams = {srcBatchPicDescs, dstBatchPicDescs, cropAreas, nullptr, totalRoiNums,
            roiNumsAddress, size};

        // launch task
        const aclError launchTaskRet = LaunchTaskForVpcBatchCrop(channelDesc, batchParams, resizeConfig, stream);
        if (launchTaskRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch task for vpc batch crop failed, errorCode = %d.", launchTaskRet);
            return launchTaskRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy output data
            const aclError validCpyRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                                   ACL_MEMCPY_DEVICE_TO_HOST,
                                                                   totalRoiNums,
                                                                   stream);
            if (validCpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to host failed, "
                    "result = %d.", validCpyRet);
                return validCpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *const channelDesc,
                                                            acldvppBatchPicDesc *const srcBatchPicDescs,
                                                            uint32_t *const roiNums,
                                                            const uint32_t size,
                                                            acldvppBatchPicDesc *const dstBatchPicDescs,
                                                            acldvppRoiConfig *cropAreas[],
                                                            acldvppResizeConfig *const resizeConfig,
                                                            const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizeAsync");
        const auto ret = DvppVpcBatchCropResizeAsync(channelDesc, srcBatchPicDescs, roiNums, size, dstBatchPicDescs,
            cropAreas, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropResize]execute acldvppVpcBatchCropResizeAsync failed, "
                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop and resize tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropAsync(acldvppChannelDesc *const channelDesc,
                                                      acldvppBatchPicDesc *const srcBatchPicDescs,
                                                      uint32_t *const roiNums,
                                                      const uint32_t size,
                                                      acldvppBatchPicDesc *const dstBatchPicDescs,
                                                      acldvppRoiConfig *cropAreas[],
                                                      const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAsync.");
        const auto ret = DvppVpcBatchCropResizeAsync(channelDesc, srcBatchPicDescs, roiNums, size, dstBatchPicDescs,
            cropAreas, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCrop]execute acldvppVpcBatchCropAsync failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcCropResizePasteAsync(const acldvppChannelDesc *const channelDesc,
                                                         const acldvppPicDesc *const inputDesc,
                                                         const acldvppPicDesc *const outputDesc,
                                                         const acldvppRoiConfig *const cropArea,
                                                         const acldvppRoiConfig *const pasteArea,
                                                         acldvppResizeConfig *const resizeConfig,
                                                         const bool resizeConfigSwitch,
                                                         const aclrtStream stream) const
    {
        uint32_t resizeConfigSize = 0U;
        const aclError validateRet = ValidateParamForDvppVpcCropResizePaste(channelDesc, inputDesc, outputDesc,
            cropArea, pasteArea, true, resizeConfig, resizeConfigSwitch, resizeConfigSize);
        if (validateRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][Params]verify params for DvppVpcCropResizePaste failed, "
                "ret = %d", validateRet);
            return validateRet;
        }
        // CropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        constexpr size_t cropAreaConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        constexpr size_t pasteAreaConfigSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + cropAreaConfigSize +
            pasteAreaConfigSize + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);

        constexpr size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
            &(cropArea->dvppRoiConfig), cropAreaConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Area]copy crop area to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        constexpr size_t pasteAreaOffset = cropAreaOffset + cropAreaConfigSize;
        memcpyRet = memcpy_s(args.get() + pasteAreaOffset, (argsSize - pasteAreaOffset),
            &(pasteArea->dvppRoiConfig), pasteAreaConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Area]copy paste area to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (resizeConfigSwitch) {
            constexpr const size_t resizeConfigOffset = pasteAreaOffset + pasteAreaConfigSize;
            memcpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                &(resizeConfig->dvppResizeConfig), static_cast<size_t>(resizeConfigSize));
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][ResizeConfig]copy resize config to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
        }

        if (aclRunMode_ == ACL_HOST) {
            aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_AND_PASTE;
        if (resizeConfigSwitch) {
            kernelName = acl::dvpp::DVPP_KERNELNAME_CROP_RESIZE_PASTE;
        }
        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = acl::dvpp::CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                            acldvppPicDesc *const inputDesc,
                                                            acldvppPicDesc *const outputDesc,
                                                            acldvppRoiConfig *const cropArea,
                                                            acldvppRoiConfig *const pasteArea,
                                                            acldvppResizeConfig *const resizeConfig,
                                                            const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropResizePasteAsync.");
        const auto ret = DvppVpcCropResizePasteAsync(channelDesc, inputDesc, outputDesc, cropArea,
            pasteArea, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][CropResizePaste]execute acldvppVpcCropResizePasteAsync "
                "failed, errorCode = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop, resize and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         acldvppRoiConfig *const cropArea,
                                                         acldvppRoiConfig *const pasteArea,
                                                         const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcCropAndPasteAsync.");
        const auto ret = DvppVpcCropResizePasteAsync(channelDesc, inputDesc, outputDesc, cropArea,
            pasteArea, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][CropAndPaste]execute acldvppVpcCropAndPasteAsync failed, errorCode = %d.",
                ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc crop and paste tasks success.");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::DvppVpcBatchCropResizePasteAsync(const acldvppChannelDesc *const channelDesc,
                                                              acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              const uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              acldvppRoiConfig *cropAreas[],
                                                              acldvppRoiConfig *pasteAreas[],
                                                              acldvppResizeConfig *const resizeConfig,
                                                              const bool resizeConfigSwitch,
                                                              const aclrtStream stream) const
    {
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(srcBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs);
        ACL_REQUIRES_NOT_NULL(dstBatchPicDescs->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(cropAreas);
        ACL_REQUIRES_NOT_NULL(pasteAreas);
        ACL_REQUIRES_NOT_NULL(roiNums);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        if (resizeConfigSwitch) {
            ACL_REQUIRES_NOT_NULL(resizeConfig);
        }

        // valid input param
        const std::unique_ptr<uint16_t[]> devRoiNums(new (std::nothrow)uint16_t[size]);
        if (devRoiNums == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][devRoiNums]create device roiNums failed, "
                "roiNums size = %u.", size);
            return ACL_ERROR_INVALID_PARAM;
        }
        uint32_t totalRoiNums = 0U;
        const aclError validParamRet = ValidateAndConvertVpcBatchParams(srcBatchPicDescs,
                                                                        dstBatchPicDescs,
                                                                        roiNums,
                                                                        size,
                                                                        devRoiNums.get(),
                                                                        totalRoiNums,
                                                                        BATCH_ROI_MAX_SIZE,
                                                                        resizeConfig);
        if (validParamRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Check][ValidParam]verify batch crop and paste param failed, "
                "result = %d.", validParamRet);
            return validParamRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy batch picDesc data
            aclError cpyRet = CopyDvppBatchPicDescAsync(srcBatchPicDescs,
                                                        ACL_MEMCPY_HOST_TO_DEVICE,
                                                        size,
                                                        stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy input batch pic desc to device failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }

            cpyRet = CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                               ACL_MEMCPY_HOST_TO_DEVICE,
                                               totalRoiNums,
                                               stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to device failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }
        } else {
            // set data buffer for input batch pic desc
            aclError setDataRet = SetDataBufferForBatchPicDesc(srcBatchPicDescs, size);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]set data buffer for src batch pic desc failed, "
                    "result = %d.", setDataRet);
                return setDataRet;
            }

            setDataRet = SetDataBufferForBatchPicDesc(dstBatchPicDescs, totalRoiNums);
            if (setDataRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Set][DataBuffer]set data buffer for dst batch pic desc failed, "
                    "result = %d.", setDataRet);
                return setDataRet;
            }
        }

        void *const roiNumsAddr = static_cast<void *>(devRoiNums.get());
        const VpcBatchParams batchParams = {srcBatchPicDescs,
                                            dstBatchPicDescs,
                                            cropAreas,
                                            pasteAreas,
                                            totalRoiNums,
                                            roiNumsAddr,
                                            size};

        // launch task
        const aclError launchTaskRet = LaunchTaskForVpcBatchCropAndPaste(channelDesc,
            batchParams, resizeConfig, stream);
        if (launchTaskRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch task for vpc batch crop and paste failed, "
                "result = %d.", launchTaskRet);
            return launchTaskRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            // copy output data
            const aclError cpyRet = acl::dvpp::CopyDvppBatchPicDescAsync(dstBatchPicDescs,
                                                                         ACL_MEMCPY_DEVICE_TO_HOST,
                                                                         totalRoiNums,
                                                                         stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][BatchPicDesc]copy output batch pic desc to host failed, "
                    "result = %d.", cpyRet);
                return cpyRet;
            }
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *const channelDesc,
                                                                 acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                 uint32_t *const roiNums,
                                                                 const uint32_t size,
                                                                 acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                 acldvppRoiConfig *cropAreas[],
                                                                 acldvppRoiConfig *pasteAreas[],
                                                                 acldvppResizeConfig *const resizeConfig,
                                                                 const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropResizePasteAsync.");
        const auto ret = DvppVpcBatchCropResizePasteAsync(channelDesc, srcBatchPicDescs,
            roiNums, size, dstBatchPicDescs,
            cropAreas, pasteAreas, resizeConfig, true, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropResizePaste]execute acldvppVpcBatchCropResizePasteAsync failed, "
                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop, resize and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *const channelDesc,
                                                              acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              acldvppRoiConfig *cropAreas[],
                                                              acldvppRoiConfig *pasteAreas[],
                                                              const aclrtStream stream)
    {
        // validate parametes
        ACL_LOG_INFO("start to execute acldvppVpcBatchCropAndPasteAsync.");
        const auto ret = DvppVpcBatchCropResizePasteAsync(channelDesc, srcBatchPicDescs, roiNums, size,
            dstBatchPicDescs, cropAreas, pasteAreas, nullptr, false, stream);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Exec][BatchCropAndPaste]execute acldvppVpcBatchCropAndPasteAsync failed, "
                "result = %d.", ret);
            return ret;
        }
        ACL_LOG_INFO("Launch vpc batch crop and paste tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppVpcConvertColorAsync(acldvppChannelDesc *const channelDesc,
                                                         acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc convert color api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc convert color api", "Please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcPyrDownAsync(acldvppChannelDesc *const channelDesc,
                                                    acldvppPicDesc *const inputDesc,
                                                    acldvppPicDesc *const outputDesc,
                                                    void* const reserve,
                                                    const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(reserve);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc pyramid down api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc pyramid down api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *const channelDesc,
                                                         const acldvppPicDesc *const inputDesc,
                                                         acldvppPicDesc *const outputDesc,
                                                         const acldvppLutMap *const lutMap,
                                                         const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(lutMap);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc equalize "
            "hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc equalize hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcMakeBorderAsync(const acldvppChannelDesc *const channelDesc,
                                                       const acldvppPicDesc *const inputDesc,
                                                       acldvppPicDesc *const outputDesc,
                                                       const acldvppBorderConfig *const borderConfig,
                                                       const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(inputDesc);
        (void)(outputDesc);
        (void)(borderConfig);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc make border api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc make border api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *const channelDesc,
                                                                      acldvppBatchPicDesc *const srcBatchPicDescs,
                                                                      uint32_t *const roiNums,
                                                                      const uint32_t size,
                                                                      acldvppBatchPicDesc *const dstBatchPicDescs,
                                                                      acldvppRoiConfig *cropAreas[],
                                                                      acldvppBorderConfig *borderCfgs[],
                                                                      acldvppResizeConfig *const resizeConfig,
                                                                      const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(srcBatchPicDescs);
        (void)(roiNums);
        (void)(size);
        (void)(dstBatchPicDescs);
        (void)(cropAreas);
        (void)(borderCfgs);
        (void)(resizeConfig);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc batch crop, resize and make border api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc make border api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppVpcCalcHistAsync(acldvppChannelDesc *const channelDesc,
                                                     acldvppPicDesc *const srcPicDesc,
                                                     acldvppHist *const hist,
                                                     void *const reserve,
                                                     const aclrtStream stream) const
    {
        (void)(channelDesc);
        (void)(srcPicDesc);
        (void)(hist);
        (void)(reserve);
        (void)(stream);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support vpc "
            "calculate hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc calculate hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    acldvppHist* ImageProcessor::acldvppCreateHist() const
    {
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return nullptr;
    }

    aclError ImageProcessor::acldvppDestroyHist(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppClearHist(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    uint32_t ImageProcessor::acldvppGetHistDims(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return 0U;
    }

    aclError ImageProcessor::acldvppGetHistData(acldvppHist *const hist, const uint32_t dim,
        uint32_t **const data, uint16_t *const len) const
    {
        (void)(hist);
        (void)(dim);
        (void)(data);
        (void)(len);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    uint32_t ImageProcessor::acldvppGetHistRetCode(acldvppHist *const hist) const
    {
        (void)(hist);
        ACL_LOG_ERROR("[Unsupport][Version]This version can not support "
            "vpc hist api. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"vpc hist api", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return 0U;
    }

    aclError ImageProcessor::acldvppJpegDecodeAsync(acldvppChannelDesc *const channelDesc,
                                                    const void *const data,
                                                    const uint32_t size,
                                                    acldvppPicDesc *const outputDesc,
                                                    const aclrtStream stream)
    {
        ACL_LOG_INFO("start to execute acldvppJpegDecodeAsync.");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        const aclError validOutputRet = ValidateJpegOutputFormat(
            static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format));
        if (validOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][JpegOutputFormat]output acldvppPicDesc format "
                "verify failed, errorCode = %d, format = %u.", validOutputRet, outputDesc->dvppPicDesc.format);
            return validOutputRet;
        }

        // jpegd have 3 input
        constexpr uint32_t ioAddrNum = 3U;
        constexpr uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)) + sizeof(uint32_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        int32_t i = 0;
        ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        const auto sizeVal = reinterpret_cast<uint32_t *>(args.get() + sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        *sizeVal = size;

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), argsSize,
            acl::dvpp::DVPP_KERNELNAME_DECODE_JPEG, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy output pic desc from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("Launch jpeg decode tasks success.");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppJpegEncodeAsync(acldvppChannelDesc *const channelDesc,
                                                    acldvppPicDesc *const inputDesc,
                                                    const void *const data,
                                                    uint32_t *const size,
                                                    acldvppJpegeConfig *const config,
                                                    const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppJpegEncodeAsync.");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(channelDesc->shareBuffer.data);
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(inputDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(size);
        ACL_REQUIRES_NOT_NULL(config);
        ACL_REQUIRES_POSITIVE(*size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        const aclError validOutputRet = ValidateJpegInputFormat(
            static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format));
        if (validOutputRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Verify][PicDesc]input acldvppPicDesc format verify failed, errorCode = %d,\
                format = %u.", validOutputRet, inputDesc->dvppPicDesc.format);
            return validOutputRet;
        }

        // jpeg encode have 4 input
        constexpr uint32_t ioAddrNum = 4U;
        const size_t dvppJpegeConfigSize = CalDevDvppStructRealUsedSize(&config->dvppJpegeConfig);
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)) + dvppJpegeConfigSize + sizeof(uint32_t);
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        int32_t i = 0;
        ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(inputDesc->dataBuffer.data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(data);
        ++i;
        // use share buffer transfer size
        ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->shareBuffer.data);

        // copy jpeg encode config size to device by args.
        constexpr size_t configOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        auto memcpyRet = memcpy_s(args.get() + configOffset, (argsSize - configOffset),
                                  &(config->dvppJpegeConfig), dvppJpegeConfigSize);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][JpegeConfig]copy jpege config to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        // copy output buffer size to device by args.
        const size_t bufferSizeOffset = configOffset + dvppJpegeConfigSize;
        memcpyRet = memcpy_s(args.get() + bufferSizeOffset, (argsSize - bufferSizeOffset), size,
            sizeof(uint32_t));
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][Buffer]copy output buffer size to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            acl::dvpp::DVPP_KERNELNAME_ENCODE_JPEG, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(inputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][Config]copy jpege config from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }

            const rtError_t rtRet = rtMemcpyAsync(size, sizeof(uint32_t),
                                            channelDesc->shareBuffer.data, sizeof(uint32_t),
                                            RT_MEMCPY_DEVICE_TO_HOST, stream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_INNER_ERROR("[Copy][JpegeSize]copy jpege size back to host failed, "
                    "runtime errorCode = %d.", rtRet);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        } else {
            // copy size to host
            const auto rtRet = rtMemcpyAsync(size, sizeof(uint32_t),
                                       channelDesc->shareBuffer.data, sizeof(uint32_t),
                                       RT_MEMCPY_DEVICE_TO_HOST_EX, stream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_INNER_ERROR("[Copy][JpegeSize]copy jpege size to host failed, runtime errorCode = %d.", rtRet);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
        }

        ACL_LOG_INFO("Launch jpeg encode tasks success");
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppPngGetImageInfo(const void *const data,
                                                    const uint32_t dataSize,
                                                    uint32_t *const width,
                                                    uint32_t *const height,
                                                    int32_t *const components) const
    {
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(width);
        ACL_REQUIRES_NOT_NULL(height);
        ACL_REQUIRES_NOT_NULL(components);

        const aclError ret = GetPngImgInfo(data, dataSize, width, height, components, nullptr);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Get][PngInfo]get png info failed, errorCode = %d.", ret);
            return ret;
        }

        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppPngPredictDecSize(const void *const data,
                                                      const uint32_t dataSize,
                                                      const acldvppPixelFormat outputPixelFormat,
                                                      uint32_t *const decSize) const
    {
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(decSize);
        if ((outputPixelFormat != PIXEL_FORMAT_RGB_888) && (outputPixelFormat != PIXEL_FORMAT_RGBA_8888) &&
            (outputPixelFormat != PIXEL_FORMAT_UNKNOWN)) {
            ACL_LOG_INNER_ERROR("[Unsupported][Format]the current outputPixelFormat[%d] is not support, "
                "only support RGB_888, RGBA_8888 and UNKNOWN", static_cast<int32_t>(outputPixelFormat));
            return ACL_ERROR_FORMAT_NOT_MATCH;
        }

        uint32_t width = 0U;
        uint32_t height = 0U;
        uint32_t bitDepth = 0U;
        const aclError ret = GetPngImgInfo(data, dataSize, &width, &height, nullptr, &bitDepth);
        if (ret != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Get][PngInfo]get png info failed, errorCode = %d.", ret);
            return ret;
        }

        // param according dvpp capability
        constexpr uint32_t pngdMaxHeight = 4096U;
        constexpr uint32_t pngdMaxWidth = 4096U;
        constexpr uint32_t pngdMinHeight = 32U;
        constexpr uint32_t pngdMinWidth = 32U;
        ACL_CHECK_WITH_MESSAGE_AND_RETURN((width >= pngdMinWidth) && (width <= pngdMaxWidth),
            ACL_ERROR_INVALID_PARAM, "png width = %u invalid, it should be between in [%u, %u].", width,
            pngdMinWidth, pngdMaxWidth);
        ACL_CHECK_WITH_MESSAGE_AND_RETURN((height >= pngdMinHeight) && (height <= pngdMaxHeight),
            ACL_ERROR_INVALID_PARAM, "png height = %u invalid, it should be between in [%u, %u].", height,
            pngdMinHeight, pngdMaxHeight);

        width = (width + 127U) & (~static_cast<uint32_t>(127U)); // width align to 128
        height = (height + 15U) & (~static_cast<uint32_t>(15U));        // align to 16
        switch (outputPixelFormat) {
            case acldvppPixelFormat::PIXEL_FORMAT_RGB_888:
                width = ((width * bitDepth * 3U) + 7U) >> 3U; // 3 represents rgb has 3 byte, 7 is padding
                break;
            case acldvppPixelFormat::PIXEL_FORMAT_UNKNOWN:
            case acldvppPixelFormat::PIXEL_FORMAT_RGBA_8888:
                width = ((width * bitDepth * 4U) + 7U) >> 3U; // 4 represents rgba has 4 byte, 7 is padding
                break;
            default:
                ACL_LOG_INNER_ERROR("[Invalid][Kind]invalid kind of outputPixelFormat[%d]",
                    static_cast<int32_t>(outputPixelFormat));
                return ACL_ERROR_FORMAT_NOT_MATCH;
        }
        *decSize = width * height;
        ACL_CHECK_WITH_MESSAGE_AND_RETURN((*decSize > 0U) && (*decSize <= DVPP_PNGD_MAX_OUTPUT_SIZE),
            ACL_ERROR_INVALID_PARAM, "pngd output size = %u invalid, it should be between in (0, %u].",
            *decSize, DVPP_PNGD_MAX_OUTPUT_SIZE);
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppPngDecodeAsync(acldvppChannelDesc *const channelDesc,
                                                   const void *const data,
                                                   const uint32_t size,
                                                   acldvppPicDesc *const outputDesc,
                                                   const aclrtStream stream) const
    {
        ACL_LOG_INFO("start to execute acldvppPngDecodeAsync");
        ACL_REQUIRES_NOT_NULL(channelDesc);
        ACL_REQUIRES_NOT_NULL(channelDesc->dataBuffer.data);
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(outputDesc);
        ACL_REQUIRES_NOT_NULL(outputDesc->dataBuffer.data);
        ACL_REQUIRES_POSITIVE(size);
        if (channelDesc->isNeedNotify) {
            ACL_REQUIRES_NOT_NULL(channelDesc->notify);
        }

        const acldvppPixelFormat outputPixelFormat = static_cast<acldvppPixelFormat>(outputDesc->dvppPicDesc.format);
        if ((outputPixelFormat != PIXEL_FORMAT_RGB_888) &&
            (outputPixelFormat != PIXEL_FORMAT_UNKNOWN)) {
            ACL_LOG_INNER_ERROR("[Unsupported][PixelFormat]the current outputPixelFormat[%d] is not support, "
                "only support PIXEL_FORMAT_RGB_888, PIXEL_FORMAT_UNKNOWN", static_cast<int32_t>(outputPixelFormat));
            return ACL_ERROR_FORMAT_NOT_MATCH;
        }

        // pngd have 3 input
        const uint32_t ioAddrNum = DvppNeedCmdlistWrite() ? 4U : 3U;
        const uint32_t argsSize = static_cast<uint32_t>(sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)) + sizeof(uint32_t));
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = argsSize;
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        int32_t i = 0;
        ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(data);
        ++i;
        ioAddr[i] = reinterpret_cast<uintptr_t>(outputDesc->dataBuffer.data);
        if (DvppNeedCmdlistWrite()) {
            ++i;
            ACL_REQUIRES_OK(DvppMallocCmdlistBufferWrite(channelDesc));
            ioAddr[i] = reinterpret_cast<uintptr_t>(channelDesc->cmdListBufferWrite.data);
        }

        const auto sizeVal = reinterpret_cast<uint32_t *>(args.get() + sizeof(aicpu::AicpuParamHead) +
            (ioAddrNum * sizeof(uint64_t)));
        *sizeVal = size;

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_HOST_TO_DEVICE, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][PicDesc]copy input pic desc to device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), argsSize,
            acl::dvpp::DVPP_KERNELNAME_DECODE_PNG, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }

        if (aclRunMode_ == ACL_HOST) {
            const aclError cpyRet = CopyDvppPicDescAsync(outputDesc, ACL_MEMCPY_DEVICE_TO_HOST, stream);
            if (cpyRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Copy][Desc]copy output pic desc from device failed, errorCode = %d.", cpyRet);
                return cpyRet;
            }
        }

        ACL_LOG_INFO("launch png decode task success");

        return ACL_SUCCESS;
    }

    aclError ImageProcessor::GetPngImgInfo(const void *const data,
                                           const uint32_t dataSize,
                                           uint32_t *const width,
                                           uint32_t *const height,
                                           int32_t *const components,
                                           uint32_t *const bitDepth) const
    {
        // 29 represents png min size
        if (dataSize <= 29U) {
            ACL_LOG_INNER_ERROR("invalid png image size %u, it must be larger than 29", dataSize);
            return ACL_ERROR_INVALID_PARAM;
        }

        const uint8_t *const pngData = static_cast<const uint8_t *>(data);
        // 0, 1, 2, 3, 4, 5, 6, 7, 8 are first eight bytes of the png data and must be equal to
        // {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a}
        if ((GET_PNG_VALUE(pngData[0], pngData[1], pngData[2], pngData[3]) != 0x89504E47U) ||
            (GET_PNG_VALUE(pngData[4], pngData[5], pngData[6], pngData[7]) != 0x0D0A1A0AU)) {
            ACL_LOG_INNER_ERROR("[Check][PngImage]invalid png image");
            return ACL_ERROR_INVALID_PARAM;
        }

        if (width != nullptr) {
            // indexs of 16, 17, 18, 19 represent png width
            *width = GET_PNG_VALUE(pngData[16], pngData[17], pngData[18], pngData[19]);
        }
        if (height != nullptr) {
            // indexs of 20, 21, 22, 23 represent png width
            *height = GET_PNG_VALUE(pngData[20], pngData[21], pngData[22], pngData[23]);
        }
        if (components != nullptr) {
            // 25 represents png color type
            // 0 and 2 represents no α channel, 4 and 6 represents that exists α channel
            if (static_cast<int32_t>(pngData[25]) == 0) {
                *components = 1; // 1 represents gray bitmap
            } else if (static_cast<int32_t>(pngData[25]) == 4) {
                *components = 2; // 2 represents gray bitmap with α channel
            } else if (static_cast<int32_t>(pngData[25]) == 2) {
                *components = 3; // 3 represents RGB
            } else if (static_cast<int32_t>(pngData[25]) == 6) {
                *components = 4; // 4 represents RGBA
            } else {
                ACL_LOG_INNER_ERROR("[Check][Pngtype]invalid png color type %u, only support 0, 2, 4 or 6",
                    static_cast<uint32_t>(pngData[25]));
                return ACL_ERROR_FORMAT_NOT_MATCH;
            }
        }
        if (bitDepth != nullptr) {
            // 24 represents png bit depth
            *bitDepth = static_cast<uint32_t>(pngData[24]);
        }

        return ACL_SUCCESS;
    }

    static aclError CheckSuppotedImage(const jpeg_decompress_struct &libjpegHandler)
    {
        if (static_cast<bool>(libjpegHandler.arith_code)) {
            ACL_LOG_ERROR("arith_code is not supported currently, only support huffman code");
            const std::string errMsg("arith_code is not supported currently, only support huffman code");
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"data", "arith_code", errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG, argList, argVal, 3U);
            return ACL_ERROR_UNSUPPORTED_JPEG;
        }
        if (static_cast<bool>(libjpegHandler.progressive_mode)) {
            ACL_LOG_ERROR("progressive_mode is not supported currently");
            const std::string errMsg("progressive_mode is not supported currently");
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"data", "progressive_mode", errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG, argList, argVal, 3U);
            return ACL_ERROR_UNSUPPORTED_JPEG;
        }
        return ACL_SUCCESS;
    }

    aclError JpegdSoftManualParseSos(const uint32_t index, const uint8_t *const data, const uint32_t size,
        size_t &huffmanCnt)
    {
        if ((index + static_cast<uint32_t>(JPEG_MARK_LENGTH_INFO_LENGTH)) >= size) {
            ACL_LOG_INNER_ERROR("[Check][Index]SOS location:%u too close to the stream end:%u", index, size);
            return ACL_ERROR_FAILURE;
        }
        const uint32_t dataLength = static_cast<uint32_t>((data[index + 1U] << BYTE_LENGTH_IN_BIT)) |
                              static_cast<uint32_t>((data[index + JPEG_MARK_LENGTH_INFO_LENGTH]));
        if (dataLength <= static_cast<uint32_t>(JPEG_MARK_LENGTH_INFO_LENGTH)) {
            return ACL_SUCCESS;
        }
        if ((dataLength + index) >= size) {
            ACL_LOG_INNER_ERROR("[Check][dataLength]jpeg SOS length:%u add current location:%u out of memory:[0, %u)",
                dataLength, index, size);
            return ACL_ERROR_FAILURE;
        }

        const uint8_t *sosPtr = &data[index + JPEG_MARK_LENGTH_INFO_LENGTH + 1U];
        const uint8_t componentNum = *sosPtr++; // get the num of color component
        if ((componentNum < 1U) || (componentNum > MAX_JPEG_COMPONENT_NUM) ||
            (dataLength != (static_cast<uint32_t>(componentNum * JPEG_EACH_HUFFMAN_IDX_SPACE + JPEG_SOS_EXT_LENGTH)))) {
            ACL_LOG_INNER_ERROR("componentNum:%u invalid or sos length:%u invalid", static_cast<uint32_t>(componentNum),
                dataLength);
            return ACL_ERROR_FAILURE;
        }

        if (((index + JPEG_MARK_LENGTH_INFO_LENGTH + 1U) + (2U * componentNum)) >= size) {
            ACL_LOG_INNER_ERROR("[Check][outMemory]current location:%u add componentNum:%u is out of memory:%u",
                index, static_cast<uint32_t>(componentNum), size);
            return ACL_ERROR_FAILURE;
        }

        // parse each color component
        if (componentNum > 1U) {
            std::map<uint8_t, uint8_t> dc_huffman_used_idx; // <huffmanTableIdx, componentIdx>
            std::map<uint8_t, uint8_t> ac_huffman_used_idx; // <huffmanTableIdx, componentIdx>
            for (uint8_t i = 0U; i < componentNum; ++i) {
                const uint8_t componentIdx = *sosPtr++;
                const uint8_t dcHuffmanIdx = ((*sosPtr) & static_cast<uint8_t>(0xF0U)) >> DC_HUFFMAN_NUM_SHIFT;
                const uint8_t acHuffmanIdx = (*sosPtr) & static_cast<uint8_t>(0x0FU);
                sosPtr++;
                dc_huffman_used_idx[dcHuffmanIdx] = componentIdx;
                ac_huffman_used_idx[acHuffmanIdx] = componentIdx;
                ACL_LOG_INFO("Component:%u using dc huffman:%u ac huffman:%u", static_cast<uint32_t>(componentIdx),
                    static_cast<uint32_t>(dcHuffmanIdx), static_cast<uint32_t>(acHuffmanIdx));
            }
            // use the num of huffman table
            huffmanCnt = dc_huffman_used_idx.size() + ac_huffman_used_idx.size();
        }
        return ACL_SUCCESS;
    }

    bool JpegdSoftManualParseMarkers(const uint8_t type, uint32_t &index, const uint8_t *const data,
        const uint32_t size, size_t &huffmanCnt)
    {
        ACL_LOG_INFO("marker is %u", static_cast<uint32_t>(type));
        switch (type) {
            case MARK_SOI:
                break;
            case MARK_EOI: // encountered EOI stop retrieval
                return true;
            case MARK_SOS: // encountered SOS stop retrieval
                (void)JpegdSoftManualParseSos(index, data, size, huffmanCnt);
                return true;
            case NOT_JPEG_MARK:
                break;
            default: {
                if ((index + JPEG_MARK_LENGTH_INFO_LENGTH) >= size) {
                    break;
                }
                const uint32_t dataLength = static_cast<uint32_t>(data[index +
                    static_cast<uint32_t>(JPEG_MARK_LENGTH_INFO_LENGTH)]) |
                    static_cast<uint32_t>(data[index + 1U] << BYTE_LENGTH_IN_BIT);
                index = index + dataLength;
                break;
            }
        }
        return false;
    }

    void JpegdSoftManualScdHeader(const uint8_t *const data, const uint32_t size, size_t &huffmanCnt)
    {
        bool stopScd = false;
        for (uint32_t i = 0U; i < size; ++i) {
            if (data[i] == JPEG_MARKER) {
                // find 0xff after of marker
                while ((i < size) && (data[i] == JPEG_MARKER)) {
                    i++;
                }
                if (i >= size) {
                    return;
                }
                stopScd = JpegdSoftManualParseMarkers(data[i], i, data, size, huffmanCnt);
                if (stopScd) {
                    return;
                }
            }
        }
        return;
    }

    aclError ImageProcessor::acldvppJpegGetImageInfo(const void *const data,
                                                     const uint32_t size,
                                                     uint32_t *const width,
                                                     uint32_t *const height,
                                                     int32_t *const components,
                                                     acldvppJpegFormat *const format) const
    {
        ACL_REQUIRES_NOT_NULL(data);
        const bool noNeedGetImageInfo = (width == nullptr) && (height == nullptr) &&
                                  (components == nullptr) && (format == nullptr);
        if (noNeedGetImageInfo) {
            ACL_LOG_INFO("no need to get jpeg info");
            return ACL_SUCCESS;
        }
        struct jpeg_decompress_struct libjpegHandler;
        struct jpeg_error_mgr libjpegErrorMsg;
        libjpegHandler.err = jpeg_std_error(&libjpegErrorMsg);
        libjpegErrorMsg.error_exit = &AcldvppLibjpegErrorExit;
        jpeg_create_decompress(&libjpegHandler);
        jpeg_save_markers(&libjpegHandler, EXIF_MARKER, 0xFFFFU);
        try {
            jpeg_mem_src(&libjpegHandler, reinterpret_cast<const uint8_t *>(data),
                         static_cast<uint64_t>(size));
            (void)jpeg_read_header(&libjpegHandler, TRUE);
        } catch (...) {
            jpeg_destroy_decompress(&libjpegHandler);
            return ACL_ERROR_FAILURE;
        }
        const aclError ret = CheckSuppotedImage(libjpegHandler);
        if (ret != ACL_SUCCESS) {
            jpeg_destroy_decompress(&libjpegHandler);
            return ret;
        }
        size_t huffmanCnt = 0U;
        JpegdSoftManualScdHeader(reinterpret_cast<const uint8_t *>(data), size, huffmanCnt);
        if (huffmanCnt > MAX_SUPPORT_HUFFMAN) {
            jpeg_destroy_decompress(&libjpegHandler);
            ACL_LOG_ERROR("the num of huffman table %zu in one JPEG is larger than max capability is %u",
                huffmanCnt, static_cast<uint32_t>(MAX_SUPPORT_HUFFMAN));
            const std::string valueStr = std::to_string(huffmanCnt);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"the num of huffman table", valueStr.c_str(), "is larger than max capability[4]"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG, argList, argVal, 3U);
            return ACL_ERROR_UNSUPPORTED_JPEG;
        }

        const bool needOrientation = JudgeNeedOrientation(&libjpegHandler);
        if (width != nullptr) {
            *width = needOrientation ? static_cast<uint32_t>(libjpegHandler.image_height) :
                static_cast<uint32_t>(libjpegHandler.image_width);
        }
        if (height != nullptr) {
            *height = needOrientation ? static_cast<uint32_t>(libjpegHandler.image_width) :
                static_cast<uint32_t>(libjpegHandler.image_height);
        }
        if (components != nullptr) {
            *components = static_cast<int32_t>(libjpegHandler.num_components);
        }
        if (format != nullptr) {
            if (!GetImageFormat(libjpegHandler, format)) {
                ACL_LOG_INNER_ERROR("format is invalid");
                jpeg_destroy_decompress(&libjpegHandler);
                return ACL_ERROR_UNSUPPORTED_JPEG;
            }
        }
        // here jpeg_destroy_decompress does not throw exception according souce code in jcomapi.c
        jpeg_destroy_decompress(&libjpegHandler);
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppJpegPredictEncSize(const acldvppPicDesc *const inputDesc,
                                                       const acldvppJpegeConfig *const config,
                                                       uint32_t *const size) const
    {
        ACL_REQUIRES_NOT_NULL(inputDesc);
        ACL_REQUIRES_NOT_NULL(config);
        ACL_REQUIRES_NOT_NULL(size);
        const uint32_t &width = inputDesc->dvppPicDesc.width;
        const uint32_t &height = inputDesc->dvppPicDesc.height;
        const uint32_t &widthStride = inputDesc->dvppPicDesc.widthStride;
        const uint32_t &heightStride = inputDesc->dvppPicDesc.heightStride;

        // param according dvpp capability
        constexpr uint32_t jpegeMaxHeight     = 8192U;
        constexpr uint32_t jpegeMaxWidth      = 8192U;
        constexpr uint32_t jpegeMinHeight     = 32U;
        constexpr uint32_t jpegeMinWidth      = 32U;

        ACL_CHECK_WITH_MESSAGE_AND_RETURN((width >= jpegeMinWidth) && (width <= jpegeMaxWidth),
            ACL_ERROR_INVALID_PARAM, "width = %u invalid, it should be between in [%u, %u].", width,
            jpegeMinWidth, jpegeMaxWidth);
        ACL_CHECK_WITH_MESSAGE_AND_RETURN((height >= jpegeMinHeight) && (height <= jpegeMaxHeight),
            ACL_ERROR_INVALID_PARAM, "height = %u invalid, it should be between in [%u, %u].", height,
            jpegeMinHeight, jpegeMaxHeight);

        const acldvppPixelFormat format = static_cast<acldvppPixelFormat>(inputDesc->dvppPicDesc.format);
        ACL_CHECK_WITH_MESSAGE_AND_RETURN(ValidateJpegInputFormat(format) == ACL_SUCCESS,
            ACL_ERROR_FORMAT_NOT_MATCH, "input acldvppPicDesc format verify failed, format = %u.",
            inputDesc->dvppPicDesc.format);

        constexpr uint32_t alignSize = 16U;
        if (IsPackedFormat(format)) {
            // widthStride should be twice as width and aligned to 16
            ACL_CHECK_WITH_MESSAGE_AND_RETURN(((((width * 2U) + alignSize - 1U) &
                (~static_cast<uint32_t>(alignSize - 1U))) == widthStride),
                ACL_ERROR_INVALID_PARAM,
                "stride width = %u invalid, it should be twice as width = %u and aligned to 16.", widthStride, width);
        } else {
            // widthStride align to 16 or align to multiple of 16.
            const bool widthCondition = (widthStride >= width) && ((widthStride % alignSize) == 0U);
            ACL_CHECK_WITH_MESSAGE_AND_RETURN(widthCondition, ACL_ERROR_INVALID_PARAM,
                "stride width = %u invalid, it should be greater than or equal width = %u and aligned to 16.",
                widthStride, width);
        }

        const bool heightCondition = (heightStride == height) ||
                                ((heightStride > height) &&
                                ((heightStride % alignSize) == 0U)); // heightStride must be aligned to 16
        ACL_CHECK_WITH_MESSAGE_AND_RETURN(heightCondition, ACL_ERROR_INVALID_PARAM,
            "stride height = %u invalid, it should be equal to height = %u or greater than height and aligned to 16.",
            heightStride, height);

        ACL_CHECK_WITH_MESSAGE_AND_RETURN(CalcImageSizeKernel(widthStride, heightStride, format, size),
            ACL_ERROR_FORMAT_NOT_MATCH, "predict jpeg encode size failed.");

        constexpr uint32_t jpegeHeaderSize = 640U;
        *size += jpegeHeaderSize;
        constexpr uint32_t startAlignBytes = 128U;
        *size += startAlignBytes;
        // align to 2M bytes
        constexpr uint32_t memAlignSize = 2097152U;  // 2M
        *size = (*size + memAlignSize - 1U) & (~(memAlignSize - 1U));

        return ACL_SUCCESS;
    }

    aclError ImageProcessor::acldvppJpegPredictDecSize(const void *const data,
                                                       const uint32_t dataSize,
                                                       const acldvppPixelFormat outputPixelFormat,
                                                       uint32_t *const decSize)
    {
        ACL_REQUIRES_NOT_NULL(data);
        ACL_REQUIRES_NOT_NULL(decSize);
        ACL_CHECK_WITH_MESSAGE_AND_RETURN(ValidateJpegOutputFormat(outputPixelFormat) == ACL_SUCCESS,
            ACL_ERROR_FORMAT_NOT_MATCH, "output acldvppPicDesc format verify failed, format = %d.",
            static_cast<int32_t>(outputPixelFormat));
        aclError ret = ACL_SUCCESS;
        struct jpeg_decompress_struct libjpegHandler;
        struct jpeg_error_mgr libjpegErrorMsg;
        libjpegHandler.err = jpeg_std_error(&libjpegErrorMsg);
        libjpegErrorMsg.error_exit = &AcldvppLibjpegErrorExit;
        jpeg_create_decompress(&libjpegHandler);
        jpeg_save_markers(&libjpegHandler, EXIF_MARKER, 0xFFFFU);
        try {
            jpeg_mem_src(&libjpegHandler, reinterpret_cast<const uint8_t *>(data),
                         static_cast<uint64_t>(dataSize));
            (void)jpeg_read_header(&libjpegHandler, TRUE);
            const bool needOrientation = JudgeNeedOrientation(&libjpegHandler);
            uint32_t width = needOrientation ? static_cast<uint32_t>(libjpegHandler.image_height) :
                static_cast<uint32_t>(libjpegHandler.image_width);
            uint32_t height = needOrientation ? static_cast<uint32_t>(libjpegHandler.image_width) :
                static_cast<uint32_t>(libjpegHandler.image_height);
            ACL_LOG_INFO("width = %u, height = %u", width, height);
            // param according dvpp capability
            constexpr uint32_t jpegdMaxHeight     = 8192U;
            constexpr uint32_t jpegdMaxWidth      = 8192U;
            constexpr uint32_t jpegdMinHeight     = 32U;
            constexpr uint32_t jpegdMinWidth      = 32U;
            ACL_CHECK_WITH_MESSAGE_AND_RETURN((width >= jpegdMinWidth) && (width <= jpegdMaxWidth),
                ACL_ERROR_INVALID_PARAM, "stride width = %u invalid, it should be between in [%u, %u].", width,
                jpegdMinWidth, jpegdMaxWidth);
            ACL_CHECK_WITH_MESSAGE_AND_RETURN((height >= jpegdMinHeight) && (height <= jpegdMaxHeight),
                ACL_ERROR_INVALID_PARAM, "stride height = %u invalid, it should be between in [%u, %u].", height,
                jpegdMinHeight, jpegdMaxHeight);

            switch (outputPixelFormat) {
                case acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420:
                case acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420:
                    width = (width + 127U) & (~static_cast<uint32_t>(127U));  // align to 128
                    height = (height + 15U) & (~static_cast<uint32_t>(15U));  // align to 16
                    (void)CalcImageSizeKernel(width, height, outputPixelFormat, decSize);
                    break;
                default:
                    // output pixel format as same as input pixel format
                    ret = CalcImageSize(libjpegHandler, needOrientation, outputPixelFormat, decSize);
                    if (ret != ACL_SUCCESS) {
                        ACL_LOG_INNER_ERROR("[Predict][Decode]predict decode size failed, output pixel format = %d",
                            static_cast<int32_t>(outputPixelFormat));
                    }
                    break;
            }
        } catch (...) {
            jpeg_destroy_decompress(&libjpegHandler);
            return ACL_ERROR_FAILURE;
        }
        // here jpeg_destroy_decompress does not throw exception according souce code in jcomapi.c
        jpeg_destroy_decompress(&libjpegHandler);

        return ret;
    }

    acldvppChannelDesc *ImageProcessor::acldvppCreateChannelDesc()
    {
        ACL_LOG_INFO("start to execute acldvppCreateChannelDesc");

        acldvppChannelDesc *aclDvppChannelDescPtr = nullptr;
        switch (aclRunMode_) {
            case ACL_HOST: {
                aclDvppChannelDescPtr = CreateChannelDescOnHost();
                break;
            }
            case ACL_DEVICE: {
                aclDvppChannelDescPtr = CreateChannelDescOnDevice();
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Unknown][Mode]unknown acl run mode %d.", aclRunMode_);
                return nullptr;
            }
        }

        // check result
        if (aclDvppChannelDescPtr == nullptr) {
            ACL_LOG_INNER_ERROR("[Check][ChannelDesc]create channel desc failed. Please check.");
            return nullptr;
        }

        static std::atomic<std::uint64_t> nextChannelIndex(1U);
        aclDvppChannelDescPtr->channelIndex = nextChannelIndex++;
        // channelMode is not used in v100
        aclDvppChannelDescPtr->dvppDesc.channelMode =
            static_cast<uint32_t>(aicpu::dvpp::DVPP_CHNMODE_VPC) |
            static_cast<uint32_t>(aicpu::dvpp::DVPP_CHNMODE_JPEGD) |
            static_cast<uint32_t>(aicpu::dvpp::DVPP_CHNMODE_JPEGE) |
            static_cast<uint32_t>(aicpu::dvpp::DVPP_CHNMODE_PNGD);

        ACL_LOG_INFO("create DvppChannelDesc : channeldesc addr = %p, cmd addr = %p, share addr = %p,"
            "support type = %d", aclDvppChannelDescPtr->dataBuffer.data, aclDvppChannelDescPtr->cmdListBuffer.data,
            aclDvppChannelDescPtr->shareBuffer.data, aclDvppChannelDescPtr->dvppDesc.channelMode);
        return aclDvppChannelDescPtr;
    }

    aclError ImageProcessor::acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc) const
    {
        if (channelDesc == nullptr) {
            return ACL_SUCCESS;
        }

        if (channelDesc->isChannelAvailable) {
            ACL_LOG_ERROR("Dvpp channel should be destroyed first before running acldvppDestroyChannelDesc");
            return ACL_ERROR_RELATIVE_RESOURCE_NOT_CLEARED;
        }

        {
            const std::unique_lock<std::mutex> lk{channelDesc->mutexForTLVMap};
            channelDesc->tlvParamMap.clear();
        }

        ACL_LOG_INFO("destroy DvppChannelDesc info: channelIndex = %lu, dataLen = %lu, cmdListLen = %lu.",
            channelDesc->channelIndex, channelDesc->dataBuffer.length, channelDesc->cmdListBuffer.length);
        switch (aclRunMode_) {
            case ACL_HOST: {
                FreeDeviceBuffer(channelDesc->dataBuffer);
                FreeDvppDeviceBuffer(channelDesc->cmdListBuffer);
                FreeDvppDeviceBuffer(channelDesc->cmdListBufferWrite);
                // shareBuffer is freed with cmdListBuffer together.
                ACL_ALIGN_FREE(channelDesc);
                break;
            }
            case ACL_DEVICE: {
                FreeDvppDeviceBuffer(channelDesc->cmdListBuffer);
                FreeDvppDeviceBuffer(channelDesc->cmdListBufferWrite);
                FreeDeviceAddr(channelDesc->shareBuffer.data);
                FreeDeviceAddr(static_cast<void *>(channelDesc));
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Unknown][Mode]unkown acl run mode %d.", aclRunMode_);
                return ACL_ERROR_INTERNAL_ERROR;
            }
        }
        ACL_LOG_DEBUG("destroy channelDesc successful");
        return ACL_SUCCESS;
    }

    acldvppPicDesc *ImageProcessor::acldvppCreatePicDesc() const
    {
        acldvppPicDesc *aclPicDesc = nullptr;
        switch (aclRunMode_) {
            case ACL_HOST: {
                aclPicDesc = CreatePicDescOnHost();
                break;
            }
            case ACL_DEVICE: {
                aclPicDesc = CreatePicDescOnDevice();
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Unknown][Mode]unkown acl run mode %d.", aclRunMode_);
                return nullptr;
            }
        }
        return aclPicDesc;
    }

    aclError ImageProcessor::acldvppDestroyPicDesc(acldvppPicDesc *picDesc) const
    {
        if (picDesc == nullptr) {
            return ACL_SUCCESS;
        }

        switch (aclRunMode_) {
            case ACL_HOST: {
                FreeDeviceBuffer(picDesc->dataBuffer);
                ACL_ALIGN_FREE(picDesc);
                break;
            }
            case ACL_DEVICE: {
                FreeDeviceAddr(static_cast<void *>(picDesc));
                break;
            }
            default: {
                ACL_LOG_INNER_ERROR("[Unknown][Mode]unkown acl run mode %d.", aclRunMode_);
                return ACL_ERROR_INTERNAL_ERROR;
            }
        }
        return ACL_SUCCESS;
    }

    acldvppRoiConfig *ImageProcessor::acldvppCreateRoiConfig(const uint32_t left,
                                                             const uint32_t right,
                                                             const uint32_t top,
                                                             const uint32_t bottom) const
    {
        ACL_LOG_INFO("start to execute acldvppCreateRoiConfig, left[%u], right[%u], top[%u], bottom[%u]",
            left, right, top, bottom);
        acldvppRoiConfig *aclRoiConfig = nullptr;
        // alloc memory
        const size_t aclDvppRoiConfigSize = CalAclDvppStructSize(aclRoiConfig);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclDvppRoiConfigSize);
        void *addr = malloc(aclDvppRoiConfigSize);
        ACL_REQUIRES_NOT_NULL_RET_NULL(addr);

        // create acldvppRoiConfig in memory
        aclRoiConfig = new (addr)acldvppRoiConfig();
        if (aclRoiConfig == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][DvppRoiConfig]create aclDvppRoiConfig with function new failed");
            ACL_FREE(addr);
            return nullptr;
        }

        // set value
        aclRoiConfig->dvppRoiConfig.leftOffset = static_cast<uint16_t>(left);
        aclRoiConfig->dvppRoiConfig.rightOffset = static_cast<uint16_t>(right);
        aclRoiConfig->dvppRoiConfig.upOffset = static_cast<uint16_t>(top);
        aclRoiConfig->dvppRoiConfig.downOffset = static_cast<uint16_t>(bottom);
        return aclRoiConfig;
    }

    aclError ImageProcessor::acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig) const
    {
        ACL_FREE(roiConfig);
        return ACL_SUCCESS;
    }

    acldvppResizeConfig *ImageProcessor::acldvppCreateResizeConfig() const
    {
        ACL_LOG_INFO("start to execute acldvppCreateResizeConfig");
        acldvppResizeConfig *aclResizeConfig = nullptr;
        // malloc memory
        const size_t aclResizeConfigSize = CalAclDvppStructSize(aclResizeConfig);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclResizeConfigSize);
        void *addr = malloc(aclResizeConfigSize);
        ACL_REQUIRES_NOT_NULL_RET_NULL(addr);

        // create acldvppResizeConfig in memory
        aclResizeConfig = new (addr)acldvppResizeConfig();
        if (aclResizeConfig == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][ResizeConfig]create acldvppResizeConfig with function new failed");
            ACL_FREE(addr);
            return nullptr;
        }
        return aclResizeConfig;
    }

    aclError ImageProcessor::acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig) const
    {
        ACL_FREE(resizeConfig);
        return ACL_SUCCESS;
    }

    acldvppJpegeConfig *ImageProcessor::acldvppCreateJpegeConfig() const
    {
        acldvppJpegeConfig *aclJpegeConfig = nullptr;
        // malloc memory
        const size_t aclJpegeConfigSize = CalAclDvppStructSize(aclJpegeConfig);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclJpegeConfigSize);
        void *addr = malloc(aclJpegeConfigSize);
        ACL_REQUIRES_NOT_NULL_RET_NULL(addr);

        // create acldvppResizeConfig in memory
        aclJpegeConfig = new (addr)acldvppJpegeConfig();
        if (aclJpegeConfig == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][JpegeConfig]create acldvppJpegeConfig with function new failed");
            ACL_FREE(addr);
            return nullptr;
        }
        return aclJpegeConfig;
    }

    aclError ImageProcessor::acldvppDestroyJpegeConfig(acldvppJpegeConfig *jpegeConfig) const
    {
        ACL_FREE(jpegeConfig);
        return ACL_SUCCESS;
    }

    acldvppPicDesc *ImageProcessor::CreatePicDescOnHost() const
    {
        acldvppPicDesc *aclPicDesc = nullptr;
        // alloc host memory
        const size_t aclPicDescSize = CalAclDvppStructSize(aclPicDesc);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclPicDescSize);
        const size_t pageSize = mmGetPageSize();
        void *hostAddr = mmAlignMalloc(aclPicDescSize, pageSize);
        ACL_REQUIRES_NOT_NULL_RET_NULL(hostAddr);

        // create acldvppPicDesc in host addr
        aclPicDesc = new (hostAddr)acldvppPicDesc;
        RETURN_NULL_WITH_ALIGN_FREE(aclPicDesc, hostAddr);

        // malloc device memory for dvppPicDesc
        void *devPtr = nullptr;
        const size_t size = CalAclDvppStructSize(&aclPicDesc->dvppPicDesc);
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t ret = rtMalloc(&devPtr, size, flags, acl::ACL_MODE_ID_U16);
        if (ret != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]malloc device memory for acl dvpp pic desc failed, "
                "runtime errorCode = %d", ret);
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }

        // set data buffer
        aclPicDesc->dataBuffer.data = devPtr;
        aclPicDesc->dataBuffer.length = size;

        return aclPicDesc;
    }

    acldvppPicDesc *ImageProcessor::CreatePicDescOnDevice() const
    {
        acldvppPicDesc *aclPicDesc = nullptr;
        // alloc device memory
        void *devAddr = nullptr;
        const size_t aclPicDescSize = CalAclDvppStructSize(aclPicDesc);
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t rtErr = rtMalloc(&devAddr, aclPicDescSize, flags, acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]alloc device memory failed, size = %zu, "
                "runtime errorCode = %d", aclPicDescSize, rtErr);
            return nullptr;
        }

        // create acldvppPicDesc in device addr
        aclPicDesc = new (devAddr)acldvppPicDesc;
        if (aclPicDesc == nullptr) {
            ACL_LOG_INNER_ERROR("[Create][PicDesc]create acldvppPicDesc with function new failed");
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }

        // set data buffer
        const size_t offset = OFFSET_OF_MEMBER(acldvppPicDesc, dvppPicDesc);
        aclPicDesc->dataBuffer.data = reinterpret_cast<aicpu::dvpp::DvppPicDesc *>(
            reinterpret_cast<uintptr_t>(devAddr) + offset);
        aclPicDesc->dataBuffer.length = CalAclDvppStructSize(&aclPicDesc->dvppPicDesc);

        return aclPicDesc;
    }

    size_t ImageProcessor::GetCmdlistBuffSize() const
    {
        return acl::dvpp::DVPP_CMDLIST_BUFFER_SIZE_V100;
    }

    aclError ImageProcessor::DvppMallocInternal(void **const tmpData, const uint64_t tmpDataSize,
        const uint32_t flag) const
    {
        const rtError_t rtRet = rtDvppMallocWithFlag(tmpData, tmpDataSize, flag, acl::ACL_MODE_ID_U16);
        if (rtRet != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Alloc][Mem]alloc device memory for channel tmp buffer failed, "
                "size = %zu, runtime errorCode = %d", tmpDataSize, rtRet);
            return ACL_GET_ERRCODE_RTS(rtRet);
        }
        ACL_LOG_INFO("execute DvppMallocInternal success, flag is %u", flag);
        return ACL_SUCCESS;
    }

    acldvppChannelDesc *ImageProcessor::CreateChannelDescOnHost() const
    {
        acldvppChannelDesc *aclDvppChannelDescPtr = nullptr;
        // alloc host memory
        const size_t aclDvppChannelDescSize = CalAclDvppStructSize(aclDvppChannelDescPtr);
        ACL_REQUIRES_POSITIVE_RET_NULL(aclDvppChannelDescSize);
        const size_t pageSize = mmGetPageSize();
        void *hostAddr = mmAlignMalloc(aclDvppChannelDescSize, pageSize);
        ACL_REQUIRES_NOT_NULL_RET_NULL(hostAddr);
        // create acldvppChannelDesc in host addr
        aclDvppChannelDescPtr = new (hostAddr)acldvppChannelDesc;
        if ((aclDvppChannelDescPtr == nullptr) || (aclDvppChannelDescPtr->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_INNER_ERROR("[Create][VdecChannelDesc]create aclvdecChannelDesc with function new failed");
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }

        const auto err = memset_s(aclDvppChannelDescPtr->dvppDesc.extendInfo, acl::dvpp::DVPP_CHANNEL_DESC_TLV_LEN,
            0, acl::dvpp::DVPP_CHANNEL_DESC_TLV_LEN);
        if (err != EOK) {
            ACL_LOG_INNER_ERROR("[Set][Mem]set dvppDesc extendInfo to 0 failed, dstLen = %u, srclen = %u, "
                "result = %d.", aclDvppChannelDescPtr->dvppDesc.len, aclDvppChannelDescPtr->dvppDesc.len, err);
            aclDvppChannelDescPtr->~acldvppChannelDesc();
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }
        // alloc device mem for dataBuffer and share buffer
        const size_t dataBufferSize = CalAclDvppStructSize(&aclDvppChannelDescPtr->dvppDesc);
        const size_t totalSize =  dataBufferSize + acl::dvpp::DVPP_CHANNEL_SHARE_BUFFER_SIZE;
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        const rtError_t rtErr = rtMalloc(&aclDvppChannelDescPtr->dataBuffer.data, totalSize, flags,
            acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]alloc device memory failed, size = %zu, "
                "runtime errorCode = %d", totalSize, rtErr);
            ACL_ALIGN_FREE(hostAddr);
            return nullptr;
        }
        aclDvppChannelDescPtr->dataBuffer.length = dataBufferSize;

        // set share buffer
        aclDvppChannelDescPtr->shareBuffer.data =
            static_cast<char_t *>(aclDvppChannelDescPtr->dataBuffer.data) + dataBufferSize;
        aclDvppChannelDescPtr->shareBuffer.length = acl::dvpp::DVPP_CHANNEL_SHARE_BUFFER_SIZE;
        return aclDvppChannelDescPtr;
    }

    acldvppChannelDesc *ImageProcessor::CreateChannelDescOnDevice() const
    {
        acldvppChannelDesc *aclDvppChannelDescPtr = nullptr;
        // alloc memory
        void *devAddr = nullptr;
        const size_t aclDvppChannelDescSize = CalAclDvppStructSize(aclDvppChannelDescPtr);
        constexpr uint32_t flags = RT_MEMORY_DEFAULT | RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY;
        rtError_t rtErr = rtMalloc(&devAddr, aclDvppChannelDescSize, flags, acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_INNER_ERROR("[Alloc][Mem]alloc device memory failed, size = %zu, runtime errorCode = %d",
                aclDvppChannelDescSize, rtErr);
            return nullptr;
        }

        // create acldvppChannelDesc in device addr
        aclDvppChannelDescPtr = new (devAddr)acldvppChannelDesc;
        if ((aclDvppChannelDescPtr == nullptr) || (aclDvppChannelDescPtr->dvppDesc.extendInfo == nullptr)) {
            ACL_LOG_INNER_ERROR("[Create][ChannelDesc]create acldvppChannelDesc with function new failed");
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }

        const auto err = memset_s(aclDvppChannelDescPtr->dvppDesc.extendInfo, acl::dvpp::DVPP_CHANNEL_DESC_TLV_LEN,
            0, acl::dvpp::DVPP_CHANNEL_DESC_TLV_LEN);
        if (err != EOK) {
            ACL_LOG_INNER_ERROR("[Set][Mem]set dvppDesc extendInfo to 0 failed, dstLen = %u, srclen = %u, "
                "result = %d.", aclDvppChannelDescPtr->dvppDesc.len, aclDvppChannelDescPtr->dvppDesc.len, err);
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }

        // set data buffer
        const size_t offset = OFFSET_OF_MEMBER(acldvppChannelDesc, dvppDesc);
        aclDvppChannelDescPtr->dataBuffer.data = reinterpret_cast<aicpu::dvpp::DvppChannelDesc *>(
            reinterpret_cast<uintptr_t>(devAddr) + offset);
        aclDvppChannelDescPtr->dataBuffer.length = CalAclDvppStructSize(&aclDvppChannelDescPtr->dvppDesc);

        // malloc device addr for share buffer
        constexpr uint32_t shareBufferSize = acl::dvpp::DVPP_CHANNEL_SHARE_BUFFER_SIZE;
        rtErr = rtMalloc(&aclDvppChannelDescPtr->shareBuffer.data, static_cast<size_t>(shareBufferSize), flags,
            acl::ACL_MODE_ID_U16);
        if (rtErr != RT_ERROR_NONE) {
            ACL_LOG_CALL_ERROR("[Malloc][Mem]alloc device memory failed, size = %u, runtime errorCode = %d",
                shareBufferSize, rtErr);
            (void) rtFree(devAddr);
            devAddr = nullptr;
            return nullptr;
        }
        aclDvppChannelDescPtr->shareBuffer.length = shareBufferSize;
        return aclDvppChannelDescPtr;
    }

    aclError ImageProcessor::CreateNotifyForDvppChannel(acldvppChannelDesc *const channelDesc) const
    {
        rtError_t rtRet;
        if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
            int32_t deviceId = 0;
            rtRet = rtGetDevice(&deviceId);
            if (rtRet != ACL_SUCCESS) {
                ACL_LOG_CALL_ERROR("[Get][DeviceId]fail to get deviceId when create dvpp channel, errorCode = %d",
                    rtRet);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }

            // create notify for dvpp channel.
            rtNotify_t notify = nullptr;
            rtRet = rtNotifyCreate(deviceId, &notify);
            if (rtRet != ACL_SUCCESS) {
                ACL_LOG_CALL_ERROR("[Create][Notify]fail to create notify, errorCode = %d", rtRet);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
            channelDesc->notify = static_cast<void *>(notify);

            // get notifyId for dvpp channel.
            uint32_t notifyId = 0U;
            rtRet = rtGetNotifyID(notify, &notifyId);
            if (rtRet != ACL_SUCCESS) {
                ACL_LOG_CALL_ERROR("[Get][Notify]fail to get NotifyId, errorCode = %d", rtRet);
                (void)rtNotifyDestroy(channelDesc->notify);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
            ACL_LOG_INFO("notifyId is %u", notifyId);
            channelDesc->dvppDesc.notifyId = notifyId;
        } else {
            // create event for dvpp channel.
            rtEvent_t event = nullptr;
            rtRet = rtEventCreateWithFlag(&event, RT_EVENT_WITH_FLAG);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Create][Event]fail to create sendFrameEvent, runtime errorCode = %d", rtRet);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
            channelDesc->notify = static_cast<void *>(event);

            // get eventId for dvpp channel
            uint32_t eventId = 0U;
            rtRet = rtGetEventID(event, &eventId);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Get][EventID]fail to get eventId, runtime errorCode = %d", rtRet);
                (void)rtEventDestroy(event);
                return ACL_GET_ERRCODE_RTS(rtRet);
            }
            ACL_LOG_INFO("eventId is %u", eventId);
            channelDesc->dvppDesc.notifyId = eventId;
        }
        return ACL_SUCCESS;
    }

    void ImageProcessor::DestroyNotifyAndStream(acldvppChannelDesc *const channelDesc, const rtStream_t stream) const
    {
        ACL_LOG_DEBUG("begin to destroy notify and stream.");
        if (channelDesc == nullptr) {
            ACL_LOG_ERROR("[Check][ChannelDesc]dvpp channel desc is null.");
            const char_t *argList[] = {"param"};
            const char_t *argVal[] = {"channelDesc"};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_NULL_POINTER_MSG,
                argList, argVal, 1U);
            return;
        }

        if (stream != nullptr) {
            const rtError_t rtRet = rtStreamDestroy(stream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Stream]fail to destroy stream, runtime errorCode = %d", rtRet);
            }
        }

        if (channelDesc->notify != nullptr) {
            rtError_t rtRet;
            if (channelDesc->dvppWaitTaskType == NOTIFY_TASK) {
                rtRet = rtNotifyDestroy(static_cast<rtNotify_t>(channelDesc->notify));
                if (rtRet != RT_ERROR_NONE) {
                    ACL_LOG_CALL_ERROR("[Destroy][Notify]fail to destroy notify, runtime errorCode = %d", rtRet);
                }
            } else {
                rtRet = rtEventDestroy(static_cast<rtEvent_t>(channelDesc->notify));
                if (rtRet != RT_ERROR_NONE) {
                    ACL_LOG_CALL_ERROR("[Destroy][Event]fail to destroy event, runtime errorCode = %d", rtRet);
                }
            }
            channelDesc->notify = nullptr;
        }

        ACL_LOG_DEBUG("success to destroy notify and stream.");
    }

    void ImageProcessor::DestroyStream(const rtStream_t stream) const
    {
        ACL_LOG_DEBUG("begin to destroy stream.");

        if (stream != nullptr) {
            const rtError_t rtRet = rtStreamDestroy(stream);
            if (rtRet != RT_ERROR_NONE) {
                ACL_LOG_CALL_ERROR("[Destroy][Stream]fail to destroy stream, runtime errorCode = %d", rtRet);
            }
        }

        ACL_LOG_DEBUG("success to destroy stream.");
    }

    aclError ImageProcessor::ValidateJpegInputFormat(const acldvppPixelFormat format) const
    {
        static const std::set<acldvppPixelFormat> JPEG_INPUT_FORMAT_SET = {
            acldvppPixelFormat::PIXEL_FORMAT_YVU_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUV_SEMIPLANAR_420,
            acldvppPixelFormat::PIXEL_FORMAT_YUYV_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_UYVY_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_YVYU_PACKED_422,
            acldvppPixelFormat::PIXEL_FORMAT_VYUY_PACKED_422
        };

        std::set<acldvppPixelFormat>::const_iterator iter = JPEG_INPUT_FORMAT_SET.find(format);
        if (iter != JPEG_INPUT_FORMAT_SET.cend()) {
            return ACL_SUCCESS;
        }
        return ACL_ERROR_FORMAT_NOT_MATCH;
    }

    aclError ImageProcessor::ValidateAndConvertVpcBatchParams(const acldvppBatchPicDesc *const srcBatchPicDescs,
                                                              const acldvppBatchPicDesc *const dstBatchPicDescs,
                                                              const uint32_t *const roiNums,
                                                              const uint32_t size,
                                                              uint16_t *const deviceRoiNums,
                                                              uint32_t &totalRoiNums,
                                                              const uint32_t maxRoiNums,
                                                              const acldvppResizeConfig *const resizeConfig) const
    {
        // valid size
        bool validParam = (size == 0U) || (srcBatchPicDescs->dvppBatchPicDescs.batchSize < size);
        if (validParam) {
            ACL_LOG_ERROR("[Check][BatchSize]srcBatchPicDescs batchSize less than roiNums size or size = 0, "
                "batch size = %u, size = %u.", srcBatchPicDescs->dvppBatchPicDescs.batchSize, size);
            const std::string convertedStr = std::to_string(srcBatchPicDescs->dvppBatchPicDescs.batchSize);
            const std::string errMsg =
                acl::AclErrorLogManager::FormatStr("less than roiNums size[%u] or size = 0", size);
            const char_t *argList[] = {"param", "value", "reason"};
            const char_t *argVal[] = {"srcBatchPicDescs batchSize", convertedStr.c_str(), errMsg.c_str()};
            acl::AclErrorLogManager::ReportInputErrorWithChar(acl::INVALID_PARAM_MSG,
                argList, argVal, 3U);
            return ACL_ERROR_INVALID_PARAM;
        }

        if (resizeConfig != nullptr) {
            const aclError validResizeConfigRet = ValidateDvppResizeConfig(resizeConfig);
            if (validResizeConfigRet != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Check][ResizeConfig]resize config acldvppResizeConfig verify failed, "
                    "result = %d.", validResizeConfigRet);
                return validResizeConfigRet;
            }
        }

        // validate input format
        aclError validFormat = ACL_SUCCESS;
        for (uint32_t idx = 0U; idx < srcBatchPicDescs->dvppBatchPicDescs.batchSize; ++idx) {
            validFormat = ValidateVpcInputFormat(
                static_cast<acldvppPixelFormat>(srcBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format));
            if (validFormat != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][InputFormat]input acldvppPicDesc format verify failed, "
                    "result = %d, format = %u.", validFormat,
                    srcBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format);
                return validFormat;
            }
        }

        // validate output format
        for (uint32_t idx = 0U; idx < dstBatchPicDescs->dvppBatchPicDescs.batchSize; ++idx) {
            validFormat = ValidateVpcOutputFormat(
                static_cast<acldvppPixelFormat>(dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format));
            if (validFormat != ACL_SUCCESS) {
                ACL_LOG_INNER_ERROR("[Verify][OutputFormat]output acldvppPicDesc format verify failed, "
                    "result = %d, format = %u.", validFormat,
                    dstBatchPicDescs->aclDvppPicDescs[idx].dvppPicDesc.format);
                return validFormat;
            }
        }

        // calculate roi nums
        for (uint32_t idx = 0U; idx < size; ++idx) {
            validParam = (roiNums[idx] > static_cast<uint32_t>(UINT16_MAX)) || (roiNums[idx] == 0U);
            if (validParam) {
                ACL_LOG_INNER_ERROR("[Check][Params]roiNums index[%u] great than UINT16_MAX[65535] or its value is %u",
                    idx, roiNums[idx]);
                return ACL_ERROR_INVALID_PARAM;
            }
            deviceRoiNums[idx] = static_cast<uint16_t>(roiNums[idx]);
            totalRoiNums += roiNums[idx];
        }

        // validate total roi nums: min value is 1
        validParam = (totalRoiNums < 1U) || (totalRoiNums > maxRoiNums);
        if (validParam) {
            ACL_LOG_INNER_ERROR("[Check][Params]the value of totalRoiNums[%d] is invalid, "
                "it must be between in [%d, %d]", totalRoiNums, 1, maxRoiNums);
            return ACL_ERROR_INVALID_PARAM;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::SetDataBufferForBatchPicDesc(const acldvppBatchPicDesc *const batchPicDesc,
        const uint32_t batchSize) const
    {
        ACL_REQUIRES_NOT_NULL(batchPicDesc);
        ACL_REQUIRES_NOT_NULL(batchPicDesc->dataBuffer.data);
        if (batchPicDesc->dvppBatchPicDescs.batchSize < batchSize) {
            ACL_LOG_INNER_ERROR("[Set][DataBuffer]batchSize[%u] from batchPicDesc must be greater "
                "or equal roi batch size[%u].", batchSize, batchPicDesc->dvppBatchPicDescs.batchSize);
            return ACL_ERROR_INVALID_PARAM;
        }

        aicpu::dvpp::DvppBatchPicDesc *const devBatchPicPtr = reinterpret_cast<aicpu::dvpp::DvppBatchPicDesc *>(
            batchPicDesc->dataBuffer.data);
        devBatchPicPtr->batchSize = batchSize;
        for (size_t idx = 0U; idx < batchSize; ++idx) {
            devBatchPicPtr->dvppPicDescs[idx] = batchPicDesc->aclDvppPicDescs[idx].dvppPicDesc;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::LaunchTaskForVpcBatchCrop(const acldvppChannelDesc *const channelDesc,
                                                       const VpcBatchParams &batchParams,
                                                       const acldvppResizeConfig *const resizeConfig,
                                                       const rtStream_t stream) const
    {
        // check corp area
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            ACL_REQUIRES_NOT_NULL(batchParams.cropAreas_[idx]);
        }

        // calculate crop config total size
        constexpr const uint32_t cropAreaSize = static_cast<uint32_t>(sizeof(aicpu::dvpp::DvppRoiConfig));
        const uint32_t totalCropConfigSize = cropAreaSize * batchParams.totalRoiNums_;
        size_t resizeConfigSize = 0U;
        if (resizeConfig != nullptr) {
            resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        }

        // BatchCrop have 3 inputs
        constexpr uint32_t addrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (addrNum * sizeof(uint64_t)) +
            totalCropConfigSize + (batchParams.batchSize_ * sizeof(uint16_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = addrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(batchParams.srcBatchPicDescs_->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(batchParams.dstBatchPicDescs_->dataBuffer.data);

        size_t cropAreaOffset = sizeof(aicpu::AicpuParamHead) + (addrNum * sizeof(uint64_t));
        // copy crop config
        for (size_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            const auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                &(batchParams.cropAreas_[idx]->dvppRoiConfig), cropAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][Crop]copy crop area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            cropAreaOffset += cropAreaSize;
        }
        // copy roiNums
        auto memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                                  batchParams.roiNums_, sizeof(uint16_t) * batchParams.batchSize_);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][RoiNums]copy roiNums to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        // copy resize config
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP;
        if (resizeConfig != nullptr) {
            kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_RESIZE;
            cropAreaOffset += (sizeof(uint16_t) * batchParams.batchSize_);
            memcpyRet = memcpy_s(args.get() + cropAreaOffset, (argsSize - cropAreaOffset),
                &(resizeConfig->dvppResizeConfig), resizeConfigSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][ResizeConfig]copy resize config to args failed, "
                    "result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
        }
        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::LaunchTaskForVpcBatchCropAndPaste(const acldvppChannelDesc *const channelDesc,
                                                               const VpcBatchParams &batchParams,
                                                               const acldvppResizeConfig *const resizeConfig,
                                                               const rtStream_t stream) const
    {
        // check crop area and paste area
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            ACL_REQUIRES_NOT_NULL(batchParams.cropAreas_[idx]);
            ACL_REQUIRES_NOT_NULL(batchParams.pasteAreas_[idx]);
        }
        // 2 areas: crop area and paste area
        constexpr size_t roiAreaSize = sizeof(aicpu::dvpp::DvppRoiConfig);
        const size_t totalRoiConfigSize = roiAreaSize * 2U * batchParams.totalRoiNums_;
        size_t resizeConfigSize = 0U;
        if (resizeConfig != nullptr) {
            resizeConfigSize = CalDevDvppStructRealUsedSize(&resizeConfig->dvppResizeConfig);
        }

        // BatchCropAndPaste have 3 inputs
        constexpr uint32_t ioAddrNum = 3U;
        const size_t argsSize = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t)) + totalRoiConfigSize +
            (batchParams.batchSize_ * sizeof(uint16_t)) + resizeConfigSize;
        const std::unique_ptr<char_t[]> args(new (std::nothrow)char_t[argsSize]);
        ACL_REQUIRES_NOT_NULL(args);
        const auto paramHead = reinterpret_cast<aicpu::AicpuParamHead *>(args.get());
        paramHead->length = static_cast<uint32_t>(argsSize);
        paramHead->ioAddrNum = ioAddrNum;
        const auto ioAddr = reinterpret_cast<uint64_t *>(args.get() + sizeof(aicpu::AicpuParamHead));
        ioAddr[0] = reinterpret_cast<uintptr_t>(channelDesc->dataBuffer.data);
        ioAddr[1] = reinterpret_cast<uintptr_t>(batchParams.srcBatchPicDescs_->dataBuffer.data);
        ioAddr[2] = reinterpret_cast<uintptr_t>(batchParams.dstBatchPicDescs_->dataBuffer.data);

        size_t roiAreaOffset = sizeof(aicpu::AicpuParamHead) + (ioAddrNum * sizeof(uint64_t));
        // copy crop config
        for (uint32_t idx = 0U; idx < batchParams.totalRoiNums_; ++idx) {
            auto memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                &(batchParams.cropAreas_[idx]->dvppRoiConfig), roiAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][CropArea]copy crop area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            roiAreaOffset += roiAreaSize;

            memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                                 &(batchParams.pasteAreas_[idx]->dvppRoiConfig), roiAreaSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][PasteArea]copy paste area to args failed, result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            roiAreaOffset += roiAreaSize;
        }
        // copy roiNums
        auto memcpyRet = memcpy_s(args.get() + roiAreaOffset, (argsSize - roiAreaOffset),
                                  batchParams.roiNums_, sizeof(uint16_t) * batchParams.batchSize_);
        if (memcpyRet != EOK) {
            ACL_LOG_INNER_ERROR("[Copy][RoiNums]copy roiNums to args failed, result = %d.", memcpyRet);
            return ACL_ERROR_FAILURE;
        }

        // copy resize config
        const char_t *kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_AND_PASTE;
        if (resizeConfig != nullptr) {
            const size_t resizeConfigOffset = roiAreaOffset + (sizeof(uint16_t) * batchParams.batchSize_);
            memcpyRet = memcpy_s(args.get() + resizeConfigOffset, (argsSize - resizeConfigOffset),
                &(resizeConfig->dvppResizeConfig), resizeConfigSize);
            if (memcpyRet != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][ResizeConfig]copy resize config to args failed, "
                    "result = %d.", memcpyRet);
                return ACL_ERROR_FAILURE;
            }
            kernelName = acl::dvpp::DVPP_KERNELNAME_BATCH_CROP_RESIZE_PASTE;
        }

        const aclError launchRet = LaunchDvppTask(channelDesc, args.get(), static_cast<uint32_t>(argsSize),
            kernelName, stream);
        if (launchRet != ACL_SUCCESS) {
            ACL_LOG_INNER_ERROR("[Launch][Task]launch dvpp task failed, errorCode = %d.", launchRet);
            return launchRet;
        }
        return ACL_SUCCESS;
    }

    acldvppLutMap *ImageProcessor::acldvppCreateLutMap() const
    {
        ACL_LOG_INNER_ERROR("[Create][LutMap]acl dvpp create lut map is not supported "
            "in this version. Please check.");
        return nullptr;
    }

    aclError ImageProcessor::acldvppDestroyLutMap(acldvppLutMap *const lutMap) const
    {
        (void)(lutMap);
        ACL_LOG_INNER_ERROR("[Destroy][LutMap]acl dvpp destroy lut map is not supported "
            "in this version. Please check.");
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    uint32_t ImageProcessor::acldvppGetLutMapDims(const acldvppLutMap *const lutMap) const
    {
        (void)(lutMap);
        ACL_LOG_INNER_ERROR("[Get][LutMapDims]acl dvpp get lut map dims is not supported "
            "in this version. Please check.");
        return 0U;
    }

    aclError ImageProcessor::acldvppGetLutMapData(const acldvppLutMap *const lutMap,
                                                  const uint32_t dim,
                                                  uint8_t **const data,
                                                  uint32_t *const len) const
    {
        (void)(lutMap);
        (void)(dim);
        (void)(data);
        (void)(len);
        ACL_LOG_INNER_ERROR("[Get][LutMapData]acl dvpp get lut map data is not supported "
            "in this version. Please check.");
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    acldvppBorderConfig *ImageProcessor::acldvppCreateBorderConfig() const
    {
        ACL_LOG_INNER_ERROR("[Create][BorderConfig]acl dvpp create border config is not supported "
            "in this version. Please check.");
        return nullptr;
    }

    aclError ImageProcessor::acldvppDestroyBorderConfig(acldvppBorderConfig *const borderConfig) const
    {
        (void)(borderConfig);
        ACL_LOG_INNER_ERROR("[Destroy][BorderConfig]acl dvpp destroy border config is not supported "
            "in this version. Please check.");
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppSetChannelDescMatrix(acldvppChannelDesc *const channelDesc,
        const acldvppCscMatrix matrixFormat) const
    {
        (void)(channelDesc);
        (void)(matrixFormat);
        ACL_LOG_ERROR("[Unsupport][Feature]Setting descMatrix for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Setting descMatrix for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppGetChannelDescMatrix(const acldvppChannelDesc *const channelDesc,
        acldvppCscMatrix &matrixFormat) const
    {
        (void)(channelDesc);
        (void)(matrixFormat);
        ACL_LOG_ERROR("[Unsupport][Feature]Getting descMatrix for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Getting descMatrix for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppSetChannelDescHeight(acldvppChannelDesc *const channelDesc,
        const uint32_t height) const
    {
        (void)(channelDesc);
        (void)(height);
        ACL_LOG_ERROR("[Unsupport][Feature]Setting height for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Setting height for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppGetChannelDescHeight(const acldvppChannelDesc *const channelDesc,
        uint32_t &height) const
    {
        (void)(channelDesc);
        (void)(height);
        ACL_LOG_ERROR("[Unsupport][Feature]Getting height for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Getting height for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppSetChannelDescWidth(acldvppChannelDesc *const channelDesc,
        const uint32_t width) const
    {
        (void)(channelDesc);
        (void)(width);
        ACL_LOG_ERROR("[Unsupport][Feature]Setting width for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Setting width for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppGetChannelDescWidth(const acldvppChannelDesc *const channelDesc,
        uint32_t &width) const
    {
        (void)(channelDesc);
        (void)(width);
        ACL_LOG_ERROR("[Unsupport][Feature]Getting width for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Getting width for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::acldvppSetJpegdPrecisionMode(acldvppChannelDesc *const channelDesc,
        const acldvppJpegdPrecisionMode precisionMode) const
    {
        (void)(channelDesc);
        (void)(precisionMode);
        ACL_LOG_ERROR("[Unsupport][Feature]Setting precision mode for channel desc is not "
            "supported in this version. Please check.");
        const char_t *argList[] = {"feature", "reason"};
        const char_t *argVal[] = {"Setting precision mode for channel desc", "please check"};
        acl::AclErrorLogManager::ReportInputErrorWithChar(acl::UNSUPPORTED_FEATURE_MSG,
            argList, argVal, 2U);
        return ACL_ERROR_FEATURE_UNSUPPORTED;
    }

    aclError ImageProcessor::SetCscMatrixForCompatibility(acldvppChannelDesc *const channelDesc) const
    {
        (void)channelDesc;
        return ACL_SUCCESS;
    }

    aclError ImageProcessor::SetDvppParamToDvppChannel(acldvppChannelDesc *const channelDesc) const
    {
        uint32_t offset = 0U;
        bool setCscMatrix = false;
        const std::unique_lock<std::mutex> lk{channelDesc->mutexForTLVMap};
        for (auto &it : channelDesc->tlvParamMap) {
            ACL_REQUIRES_NOT_NULL(it.second.value.get());
            if (it.first == DVPP_CSC_MATRIX) {
                setCscMatrix = true;
            }
            uint32_t tmpOffset = offset;
            ACL_CHECK_ASSIGN_UINT32T_ADD(tmpOffset, static_cast<uint32_t>(it.second.valueLen), tmpOffset);
            if (tmpOffset > DVPP_CHANNEL_DESC_TLV_LEN) {
                ACL_LOG_INNER_ERROR("[Check][Offset] offset %u can not be larger than %u",
                    tmpOffset, DVPP_CHANNEL_DESC_TLV_LEN);
                return ACL_ERROR_FAILURE;
            }
            const auto ret = memcpy_s(channelDesc->dvppDesc.extendInfo + offset, it.second.valueLen,
                it.second.value.get(), it.second.valueLen);
            if (ret != EOK) {
                ACL_LOG_INNER_ERROR("[Copy][Mem]call memcpy_s failed, result = %d, srcLen = %zu, dstLen = %zu", ret,
                    it.second.valueLen, it.second.valueLen);
                return ACL_ERROR_FAILURE;
            }
            offset += static_cast<uint32_t>(it.second.valueLen);
        }
        channelDesc->dvppDesc.len = offset;
        if ((channelDesc->dvppDesc.len > 0U) && (!setCscMatrix)) {
            ACL_REQUIRES_OK(SetCscMatrixForCompatibility(channelDesc));
        }
        return ACL_SUCCESS;
    }
    }
}
